Skip to content

Commit

Permalink
Merge branch 'master' into CHAIN_AS_TO_SCHEMA
Browse files Browse the repository at this point in the history
 Conflicts:
	src/main/java/redis/clients/jedis/search/Schema.java
  • Loading branch information
sazzad16 committed May 26, 2022
2 parents 38342c7 + 2b7dd63 commit e1ce5fa
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 41 deletions.
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ We'd love your contributions!

**Bug reports** are always welcome! [You can open a bug report on GitHub](https://github.com/redis/jedis/issues/new).

You can also **contribute documentation** -- or anything to improve Jedis. Please see [contribution guideline](https://github.com/redis/jedis/blob/master/.github/CONTRIBUTING.md) for more details.
You can also **contribute documentation** -- or anything to improve Jedis. Please see
[contribution guideline](https://github.com/redis/jedis/blob/master/.github/CONTRIBUTING.md) for more details.

## Getting started

Expand All @@ -39,7 +40,9 @@ Next, you'll need to connect to Redis. For many applications, it's best to use a
JedisPool pool = new JedisPool("localhost", 6379);
```

Once you have a `JedisPool` instance, you can use a [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) block to get a connection and run Redis commands.
With a `JedisPool` instance, you can use a
[try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)
block to get a connection and run Redis commands.

Here's how to run a single [SET](https://redis.io/commands/set) command within a *try-with-resources* block:

Expand All @@ -49,7 +52,9 @@ try (Jedis jedis = pool.getResource()) {
}
```

`Jedis` instances implement most Redis commands. See the [Jedis Javadocs](https://www.javadoc.io/doc/redis.clients/jedis/latest/redis/clients/jedis/Jedis.html) for a complete list of supported commands.
`Jedis` instances implement most Redis commands. See the
[Jedis Javadocs](https://www.javadoc.io/doc/redis.clients/jedis/latest/redis/clients/jedis/Jedis.html)
for the complete list of supported commands.

### Easier way of using connection pool

Expand All @@ -67,7 +72,8 @@ jedis.sadd("planets", "Venus");

## Connecting to a Redis cluster

Jedis lets you connect to Redis Clusters, supporting the [Redis Cluster Specification](https://redis.io/topics/cluster-spec). To do this, you'll need to connect using `JedisCluster`. See the example below:
Jedis lets you connect to Redis Clusters, supporting the [Redis Cluster Specification](https://redis.io/topics/cluster-spec).
To do this, you'll need to connect using `JedisCluster`. See the example below:

```java
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
Expand All @@ -84,9 +90,10 @@ jedis.sadd("planets", "Mars");

## Using Redis modules

Jedis provides support for some of the [Redis modules](https://redis.io/docs/modules/), most notably [RedisJSON](https://oss.redis.com/redisjson/) and [RediSearch](https://oss.redis.com/redisearch/).
Jedis provides support for some of the [Redis modules](https://redis.io/docs/modules/), most notably
[RedisJSON](https://oss.redis.com/redisjson/) and [RediSearch](https://oss.redis.com/redisearch/).

See the [RedisJSON Jedis Quick Start](docs/redisjson.md) for details.
See the [RedisJSON Jedis](docs/redisjson.md) or [RediSearch Jedis](docs/redisearch.md) for details.

## Documentation

Expand All @@ -100,7 +107,8 @@ If you run into trouble or have any questions, we're here to help!

Hit us up on the [Redis Discord Server](http://discord.gg/redis) or [open an issue on GitHub](https://github.com/redis/jedis).

You can also find help on the [Jedis mailing list](http://groups.google.com/group/jedis_redis) or the [GitHub Discussions](https://github.com/redis/jedis/discussions).
You can also find help on the [Jedis mailing list](http://groups.google.com/group/jedis_redis) or the
[GitHub Discussions](https://github.com/redis/jedis/discussions).

## License

Expand Down
71 changes: 71 additions & 0 deletions docs/redisearch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# RediSearch Jedis Quick Start

To use RediSearch features with Jedis, you'll need to use and implementation of RediSearchCommands.

## Creating the RediSearch client

Initializing the client with JedisPooled:

```java
JedisPooled client = new JedisPooled("localhost", 6379);
```

Initializing the client with JedisCluster:

```java
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("127.0.0.1", 7379));
nodes.add(new HostAndPort("127.0.0.1", 7380));

JedisCluster client = new JedisCluster(nodes);
```

## Indexing and querying

Defining a schema for an index and creating it:

```java
Schema sc = new Schema()
.addTextField("title", 5.0)
.addTextField("body", 1.0)
.addNumericField("price");

IndexDefinition def = new IndexDefinition()
.setPrefixes(new String[]{"item:", "product:"})
.setFilter("@price>100");

client.ftCreate("item-index", IndexOptions.defaultOptions().setDefinition(def), sc);
```

Adding documents to the index:

```java
Map<String, Object> fields = new HashMap<>();
fields.put("title", "hello world");
fields.put("state", "NY");
fields.put("body", "lorem ipsum");
fields.put("price", 1337);

client.hset("item:hw", RediSearchUtil.toStringMap(fields));
```

Searching the index:

```java
// creating a complex query
Query q = new Query("hello world")
.addFilter(new Query.NumericFilter("price", 0, 1000))
.limit(0, 5);

// actual search
SearchResult sr = client.ftSearch("item-index", q);

// aggregation query
AggregationBuilder ab = new AggregationBuilder("hello")
.apply("@price/1000", "k")
.groupBy("@state", Reducers.avg("@k").as("avgprice"))
.filter("@avgprice>=2")
.sortBy(10, SortedField.asc("@state"));

AggregationResult ar = client.ftAggregate("item-index", ab);
```
59 changes: 33 additions & 26 deletions docs/redisjson.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,35 @@
Jedis supports [RedisJSON](https://oss.redis.com/redisjson/) and [RediSearch](https://oss.redis.com/redisearch/).

The latest versions of RedisJSON let you store, manipulate, index, and query JSON.
To use these features with Jedis, you'll need to use the `UnifiedJedis` interface
or a sub-class of it.
To use these features with Jedis, you'll need to use the `UnifiedJedis` interface or a sub-class of it.

Let's see how this works.

## Connecting with UnifiedJedis
## Creating with RedisJSON client

First, let's create a `UnifiedJedis` instance:
First, let's create a `JedisPooled` client instance:

```java
UnifiedJedis client = new JedisPooled(Protocol.DEFAULT_HOST, 6479);
JedisPooled client = new JedisPooled("localhost", 6479);
```
Now we can start working with JSON. For these examples, we'll be using [GSON]
(https://github.com/google/gson) to handle the serialization of POJOs to JSON.

Or, a `JedisCluster` client instance:

```java
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("127.0.0.1", 7379));
nodes.add(new HostAndPort("127.0.0.1", 7380));

JedisCluster client = new JedisCluster(nodes);
```

Now we can start working with JSON. For these examples, we'll be using [GSON](https://github.com/google/gson)
to handle the serialization of POJOs to JSON.

## Creating JSON documents

Suppose we're building an online learning platform, and we want to represent
students. Let's create a POJO to represent our students:
Suppose we're building an online learning platform, and we want to represent students.
Let's create a POJO to represent our students:

```java
private class Student {
Expand All @@ -34,11 +44,11 @@ private class Student {
}

public String getFirstName() {
return firstName;
return firstName;
}

public String getLastName() {
return lastName;
return lastName;
}
}
```
Expand All @@ -55,28 +65,22 @@ client.jsonSet("student:112", oliwia);

## Querying and indexing JSON

If we want to be able to query this JSON, we'll need to create an index. Let's
create an index on the "firstName" and "lastName" fields.
If we want to be able to query this JSON, we'll need to create an index. Let's create an index on the "firstName" and "lastName" fields.

1. We define which fields to index ("firstName" and "lastName").
2. We set up the index definition to recognize JSON and include only those
documents
whose key starts with "student:".
3. Then we actually create the index, called "student-index", by calling `ftCreate
()`.
2. We set up the index definition to recognize JSON and include only those documents whose key starts with "student:".
3. Then we actually create the index, called "student-index", by calling `ftCreate()`.

```java
Schema schema = new Schema().addTextField("$.firstName", 1.0).addTextField("$" +
".lastName", 1.0);
Schema schema = new Schema().addTextField("$.firstName", 1.0).addTextField("$" + ".lastName", 1.0);

IndexDefinition rule = new IndexDefinition(IndexDefinition.Type.JSON)
.setPrefixes(new String[]{"student:"});
client.ftCreate("student-index",
IndexOptions.defaultOptions().setDefinition(rule),
schema);

client.ftCreate("student-index", IndexOptions.defaultOptions().setDefinition(rule), schema);
```

With an index now defined, we can query our JSON. Let's find all students whose
name begins with "maya":
With an index now defined, we can query our JSON. Let's find all students whose name begins with "maya":

```java
Query q = new Query("@\\$\\" + ".firstName:maya*");
Expand All @@ -92,4 +96,7 @@ for (Document doc : docs) {
}
```

This example just scratches the surface. You can atomically manipulate JSON documents and query them in a variety of ways. See the [RedisJSON docs](https://oss.redis.com/redisjson/), the [RediSearch](https://oss.redis.com/redisearch/) docs, and our course, ["Querying, Indexing, and Full-text Search in Redis"](https://university.redis.com/courses/ru203/), for a lot more examples.
This example just scratches the surface. You can atomically manipulate JSON documents and query them in a variety of ways.
See the [RedisJSON docs](https://oss.redis.com/redisjson/), the [RediSearch](https://oss.redis.com/redisearch/) docs,
and our course, ["Querying, Indexing, and Full-text Search in Redis"](https://university.redis.com/courses/ru203/),
for a lot more examples.
59 changes: 51 additions & 8 deletions src/main/java/redis/clients/jedis/search/Schema.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public enum FieldType {
VECTOR
}

@Deprecated // TODO: this should be private
public final List<Field> fields;

public Schema() {
Expand Down Expand Up @@ -97,11 +98,31 @@ public Schema addTagField(String name, String separator) {
return this;
}

public Schema addTagField(String name, boolean caseSensitive) {
fields.add(new TagField(name, caseSensitive, false));
return this;
}

public Schema addTagField(String name, String separator, boolean caseSensitive) {
fields.add(new TagField(name, separator, caseSensitive, false));
return this;
}

public Schema addSortableTagField(String name, String separator) {
fields.add(new TagField(name, separator, true));
return this;
}

public Schema addSortableTagField(String name, boolean caseSensitive) {
fields.add(new TagField(name, caseSensitive, true));
return this;
}

public Schema addSortableTagField(String name, String separator, boolean caseSensitive) {
fields.add(new TagField(name, separator, caseSensitive, true));
return this;
}

public Schema addVectorField(String name, VectorField.VectorAlgo algorithm, Map<String, Object> attributes) {
fields.add(new VectorField(name, algorithm, attributes));
return this;
Expand Down Expand Up @@ -143,7 +164,11 @@ public static class Field implements IParams {
@Deprecated public final String name;
@Deprecated public final FieldType type;
@Deprecated public final boolean sortable;
@Deprecated public final boolean noindex;
@Deprecated public final boolean noIndex;

public Field(String name, FieldType type) {
this(name, type, false, false);
}

public Field(String name, FieldType type, boolean sortable) {
this(name, type, sortable, false);
Expand All @@ -162,7 +187,7 @@ public Field(FieldName name, FieldType type, boolean sortable, boolean noIndex)
this.name = this.fieldName.getName();
this.type = type;
this.sortable = sortable;
this.noindex = noIndex;
this.noIndex = noIndex;
}

public void as(String attribute){
Expand All @@ -177,7 +202,7 @@ public final void addParams(CommandArguments args) {
if (sortable) {
args.add("SORTABLE");
}
if (noindex) {
if (noIndex) {
args.add("NOINDEX");
}
}
Expand All @@ -191,7 +216,7 @@ protected void addTypeArgs(CommandArguments args) { }

@Override
public String toString() {
return "Field{name='" + fieldName + "', type=" + type + ", sortable=" + sortable + ", noindex=" + noindex + "}";
return "Field{name='" + fieldName + "', type=" + type + ", sortable=" + sortable + ", noindex=" + noIndex + "}";
}
}

Expand Down Expand Up @@ -259,14 +284,15 @@ protected void addTypeArgs(CommandArguments args) {

@Override
public String toString() {
return "TextField{name='" + fieldName + "', type=" + type + ", sortable=" + sortable + ", noindex=" + noindex
return "TextField{name='" + fieldName + "', type=" + type + ", sortable=" + sortable + ", noindex=" + noIndex
+ ", weight=" + weight + ", nostem=" + nostem + ", phonetic='" + phonetic + "'}";
}
}

public static class TagField extends Field {

private final String separator;
private final boolean caseSensitive;

public TagField(String name) {
this(name, null);
Expand All @@ -281,13 +307,27 @@ public TagField(String name, boolean sortable) {
}

public TagField(String name, String separator, boolean sortable) {
this(name, separator, false, sortable);
}

public TagField(String name, boolean caseSensitive, boolean sortable) {
this(name, null, caseSensitive, sortable);
}

public TagField(String name, String separator, boolean caseSensitive, boolean sortable) {
super(name, FieldType.TAG, sortable);
this.separator = separator;
this.caseSensitive = caseSensitive;
}

public TagField(FieldName name, String separator, boolean sortable) {
this(name, separator, false, sortable);
}

public TagField(FieldName name, String separator, boolean caseSensitive, boolean sortable) {
super(name, FieldType.TAG, sortable, false);
this.separator = separator;
this.caseSensitive = caseSensitive;
}

@Override
Expand All @@ -296,12 +336,15 @@ public void addTypeArgs(CommandArguments args) {
args.add("SEPARATOR");
args.add(separator);
}
if (caseSensitive) {
args.add("CASESENSITIVE");
}
}

@Override
public String toString() {
return "TagField{name='" + fieldName + "', type=" + type + ", sortable=" + sortable + ", noindex=" + noindex
+ ", separator='" + separator + "'}";
return "TagField{name='" + fieldName + "', type=" + type + ", sortable=" + sortable + ", noindex=" + noIndex
+ ", separator='" + separator + ", caseSensitive='" + caseSensitive + "'}";
}
}

Expand All @@ -316,7 +359,7 @@ public enum VectorAlgo {
private final Map<String, Object> attributes;

public VectorField(String name, VectorAlgo algorithm, Map<String, Object> attributes) {
super(name, FieldType.VECTOR, false, false);
super(name, FieldType.VECTOR);
this.algorithm = algorithm;
this.attributes = attributes;
}
Expand Down
Loading

0 comments on commit e1ce5fa

Please sign in to comment.