From dee9d7692722e8e6a57087a24ab7b290441d541a Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sat, 15 Jun 2024 20:11:41 +0600 Subject: [PATCH] Support indexing of MISSING and EMPTY values --- .../clients/jedis/search/FTSearchParams.java | 2 +- .../redis/clients/jedis/search/Query.java | 2 +- .../redis/clients/jedis/search/Schema.java | 2 +- .../clients/jedis/search/SearchProtocol.java | 2 +- .../jedis/search/aggr/AggregationBuilder.java | 4 +- .../jedis/search/querybuilder/QueryNode.java | 6 +- .../jedis/search/schemafields/GeoField.java | 33 ++++- .../search/schemafields/GeoShapeField.java | 23 +++- .../search/schemafields/NumericField.java | 14 +- .../jedis/search/schemafields/TagField.java | 78 +++++++---- .../jedis/search/schemafields/TextField.java | 85 +++++++----- .../search/schemafields/VectorField.java | 15 +- .../modules/search/SearchWithParamsTest.java | 130 ++++++++++++++++-- 13 files changed, 309 insertions(+), 87 deletions(-) diff --git a/src/main/java/redis/clients/jedis/search/FTSearchParams.java b/src/main/java/redis/clients/jedis/search/FTSearchParams.java index d2ca5d6d94..2d4c6e0057 100644 --- a/src/main/java/redis/clients/jedis/search/FTSearchParams.java +++ b/src/main/java/redis/clients/jedis/search/FTSearchParams.java @@ -143,7 +143,7 @@ public void addParams(CommandArguments args) { } if (params != null && !params.isEmpty()) { - args.add(PARAMS).add(params.size() * 2); + args.add(PARAMS).add(params.size() << 1); params.entrySet().forEach(entry -> args.add(entry.getKey()).add(entry.getValue())); } diff --git a/src/main/java/redis/clients/jedis/search/Query.java b/src/main/java/redis/clients/jedis/search/Query.java index 66cba96acf..66de3ce074 100644 --- a/src/main/java/redis/clients/jedis/search/Query.java +++ b/src/main/java/redis/clients/jedis/search/Query.java @@ -292,7 +292,7 @@ public void addParams(CommandArguments args) { if (_params != null && _params.size() > 0) { args.add(SearchKeyword.PARAMS.getRaw()); - args.add(_params.size() * 2); + args.add(_params.size() << 1); for (Map.Entry entry : _params.entrySet()) { args.add(entry.getKey()); args.add(entry.getValue()); diff --git a/src/main/java/redis/clients/jedis/search/Schema.java b/src/main/java/redis/clients/jedis/search/Schema.java index 17f01cc9de..1403aab556 100644 --- a/src/main/java/redis/clients/jedis/search/Schema.java +++ b/src/main/java/redis/clients/jedis/search/Schema.java @@ -365,7 +365,7 @@ public VectorField(String name, VectorAlgo algorithm, Map attrib @Override public void addTypeArgs(CommandArguments args) { args.add(algorithm); - args.add(attributes.size() * 2); + args.add(attributes.size() << 1); for (Map.Entry entry : attributes.entrySet()) { args.add(entry.getKey()); args.add(entry.getValue()); diff --git a/src/main/java/redis/clients/jedis/search/SearchProtocol.java b/src/main/java/redis/clients/jedis/search/SearchProtocol.java index 7f2ad482fb..64482f4fbb 100644 --- a/src/main/java/redis/clients/jedis/search/SearchProtocol.java +++ b/src/main/java/redis/clients/jedis/search/SearchProtocol.java @@ -56,7 +56,7 @@ public enum SearchKeyword implements Rawable { LANGUAGE_FIELD, SCORE, SCORE_FIELD, SCORER, PARAMS, AS, DIALECT, SLOP, TIMEOUT, INORDER, EXPANDER, MAXTEXTFIELDS, SKIPINITIALSCAN, WITHSUFFIXTRIE, NOSTEM, NOINDEX, PHONETIC, WEIGHT, CASESENSITIVE, LOAD, APPLY, GROUPBY, MAXIDLE, WITHCURSOR, DISTANCE, TERMS, INCLUDE, EXCLUDE, - SEARCH, AGGREGATE, QUERY, LIMITED, COUNT, REDUCE; + SEARCH, AGGREGATE, QUERY, LIMITED, COUNT, REDUCE, INDEXMISSING, INDEXEMPTY; private final byte[] raw; diff --git a/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java b/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java index eb8e039d02..7c8b547339 100644 --- a/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java +++ b/src/main/java/redis/clients/jedis/search/aggr/AggregationBuilder.java @@ -66,7 +66,7 @@ public AggregationBuilder limit(int count) { public AggregationBuilder sortBy(SortedField... fields) { aggrArgs.add(SearchKeyword.SORTBY); - aggrArgs.add(Integer.toString(fields.length * 2)); + aggrArgs.add(fields.length << 1); for (SortedField field : fields) { aggrArgs.add(field.getField()); aggrArgs.add(field.getOrder()); @@ -172,7 +172,7 @@ public AggregationBuilder timeout(long timeout) { public AggregationBuilder params(Map params) { aggrArgs.add(SearchKeyword.PARAMS); - aggrArgs.add(params.size() * 2); + aggrArgs.add(params.size() << 1); params.forEach((k, v) -> { aggrArgs.add(k); aggrArgs.add(v); diff --git a/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java b/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java index bc64374a5a..f5759b553d 100644 --- a/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java +++ b/src/main/java/redis/clients/jedis/search/querybuilder/QueryNode.java @@ -61,11 +61,11 @@ public QueryNode add(Node... nodes) { protected boolean shouldParenthesize(Parenthesize mode) { if (mode == Parenthesize.ALWAYS) { return true; - } - if (mode == Parenthesize.NEVER) { + } else if (mode == Parenthesize.NEVER) { return false; + } else { + return children.size() > 1; } - return children.size() > 1; } @Override diff --git a/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java b/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java index 7ea421ab4f..c5878f21b8 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/GeoField.java @@ -1,12 +1,16 @@ package redis.clients.jedis.search.schemafields; -import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.GEO; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.search.FieldName; public class GeoField extends SchemaField { + private boolean indexMissing; + private boolean sortable; + private boolean noIndex; + public GeoField(String fieldName) { super(fieldName); } @@ -29,9 +33,36 @@ public GeoField as(String attribute) { return this; } + public GeoField indexMissing() { + this.indexMissing = true; + return this; + } + + public GeoField sortable() { + this.sortable = true; + return this; + } + + public GeoField noIndex() { + this.noIndex = true; + return this; + } + @Override public void addParams(CommandArguments args) { args.addParams(fieldName); args.add(GEO); + + if (indexMissing) { + args.add(INDEXMISSING); + } + + if (sortable) { + args.add(SORTABLE); + } + + if (noIndex) { + args.add(NOINDEX); + } } } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java b/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java index dd3b45e59e..fedfed1297 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/GeoShapeField.java @@ -1,6 +1,6 @@ package redis.clients.jedis.search.schemafields; -import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.GEOSHAPE; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.search.FieldName; @@ -22,6 +22,9 @@ public enum CoordinateSystem { private final CoordinateSystem system; + private boolean indexMissing; + private boolean noIndex; + public GeoShapeField(String fieldName, CoordinateSystem system) { super(fieldName); this.system = system; @@ -42,8 +45,26 @@ public GeoShapeField as(String attribute) { return this; } + public GeoShapeField indexMissing() { + this.indexMissing = true; + return this; + } + + public GeoShapeField noIndex() { + this.noIndex = true; + return this; + } + @Override public void addParams(CommandArguments args) { args.addParams(fieldName).add(GEOSHAPE).add(system); + + if (indexMissing) { + args.add(INDEXMISSING); + } + + if (noIndex) { + args.add(NOINDEX); + } } } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/NumericField.java b/src/main/java/redis/clients/jedis/search/schemafields/NumericField.java index e1e39ef724..244cc42640 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/NumericField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/NumericField.java @@ -1,14 +1,13 @@ package redis.clients.jedis.search.schemafields; -import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.NOINDEX; -import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.NUMERIC; -import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.SORTABLE; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.*; import redis.clients.jedis.CommandArguments; import redis.clients.jedis.search.FieldName; public class NumericField extends SchemaField { + private boolean indexMissing; private boolean sortable; private boolean noIndex; @@ -34,6 +33,11 @@ public NumericField as(String attribute) { return this; } + public NumericField indexMissing() { + this.indexMissing = true; + return this; + } + /** * Sorts the results by the value of this field. */ @@ -55,6 +59,10 @@ public void addParams(CommandArguments args) { args.addParams(fieldName); args.add(NUMERIC); + if (indexMissing) { + args.add(INDEXMISSING); + } + if (sortable) { args.add(SORTABLE); } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/TagField.java b/src/main/java/redis/clients/jedis/search/schemafields/TagField.java index 407c4dbddc..451b12aad5 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/TagField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/TagField.java @@ -8,12 +8,14 @@ public class TagField extends SchemaField { - private boolean sortable; - private boolean sortableUNF; - private boolean noIndex; + private boolean indexMissing; + private boolean indexEmpty; private byte[] separator; private boolean caseSensitive; private boolean withSuffixTrie; + private boolean sortable; + private boolean sortableUNF; + private boolean noIndex; public TagField(String fieldName) { super(fieldName); @@ -37,39 +39,19 @@ public TagField as(String attribute) { return this; } - /** - * Sorts the results by the value of this field. - */ - public TagField sortable() { - this.sortable = true; - return this; - } - - /** - * Sorts the results by the value of this field without normalization. - */ - public TagField sortableUNF() { - this.sortableUNF = true; + public TagField indexMissing() { + this.indexMissing = true; return this; } - /** - * @see TextField#sortableUNF() - */ - public TagField sortableUnNormalizedForm() { - return sortableUNF(); - } - - /** - * Avoid indexing. - */ - public TagField noIndex() { - this.noIndex = true; + public TagField indexEmpty() { + this.indexEmpty = true; return this; } /** * Indicates how the text contained in the attribute is to be split into individual tags. + * @param separator */ public TagField separator(char separator) { if (separator < 128) { @@ -97,11 +79,51 @@ public TagField withSuffixTrie() { return this; } + /** + * Sorts the results by the value of this field. + */ + public TagField sortable() { + this.sortable = true; + return this; + } + + /** + * Sorts the results by the value of this field without normalization. + */ + public TagField sortableUNF() { + this.sortableUNF = true; + return this; + } + + /** + * @deprecated Use {@code TagField#sortableUNF()}. + * @see TagField#sortableUNF() + */ + @Deprecated + public TagField sortableUnNormalizedForm() { + return sortableUNF(); + } + + /** + * Avoid indexing. + */ + public TagField noIndex() { + this.noIndex = true; + return this; + } + @Override public void addParams(CommandArguments args) { args.addParams(fieldName); args.add(TAG); + if (indexMissing) { + args.add(INDEXMISSING); + } + if (indexEmpty) { + args.add(INDEXEMPTY); + } + if (separator != null) { args.add(SEPARATOR).add(separator); } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/TextField.java b/src/main/java/redis/clients/jedis/search/schemafields/TextField.java index 573cae90a3..293104a189 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/TextField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/TextField.java @@ -7,13 +7,15 @@ public class TextField extends SchemaField { - private boolean sortable; - private boolean sortableUNF; + private boolean indexMissing; + private boolean indexEmpty; + private Double weight; private boolean noStem; - private boolean noIndex; private String phoneticMatcher; - private Double weight; private boolean withSuffixTrie; + private boolean sortable; + private boolean sortableUNF; + private boolean noIndex; public TextField(String fieldName) { super(fieldName); @@ -37,27 +39,24 @@ public TextField as(String attribute) { return this; } - /** - * Sorts the results by the value of this field. - */ - public TextField sortable() { - this.sortable = true; + public TextField indexMissing() { + this.indexMissing = true; return this; } - /** - * Sorts the results by the value of this field without normalization. - */ - public TextField sortableUNF() { - this.sortableUNF = true; + public TextField indexEmpty() { + this.indexEmpty = true; return this; } /** - * @see TextField#sortableUNF() + * Declares the importance of this attribute when calculating result accuracy. This is a + * multiplication factor. + * @param weight */ - public TextField sortableUnNormalizedForm() { - return sortableUNF(); + public TextField weight(double weight) { + this.weight = weight; + return this; } /** @@ -69,36 +68,53 @@ public TextField noStem() { } /** - * Avoid indexing. + * Perform phonetic matching. + * @param matcher */ - public TextField noIndex() { - this.noIndex = true; + public TextField phonetic(String matcher) { + this.phoneticMatcher = matcher; return this; } /** - * Perform phonetic matching. + * Keeps a suffix trie with all terms which match the suffix. It is used to optimize + * contains and suffix queries. */ - public TextField phonetic(String matcher) { - this.phoneticMatcher = matcher; + public TextField withSuffixTrie() { + this.withSuffixTrie = true; return this; } /** - * Declares the importance of this attribute when calculating result accuracy. This is a - * multiplication factor. + * Sorts the results by the value of this field. */ - public TextField weight(double weight) { - this.weight = weight; + public TextField sortable() { + this.sortable = true; return this; } /** - * Keeps a suffix trie with all terms which match the suffix. It is used to optimize - * contains and suffix queries. + * Sorts the results by the value of this field without normalization. */ - public TextField withSuffixTrie() { - this.withSuffixTrie = true; + public TextField sortableUNF() { + this.sortableUNF = true; + return this; + } + + /** + * @deprecated Use {@code TextField#sortableUNF()}. + * @see TextField#sortableUNF() + */ + @Deprecated + public TextField sortableUnNormalizedForm() { + return sortableUNF(); + } + + /** + * Avoid indexing. + */ + public TextField noIndex() { + this.noIndex = true; return this; } @@ -107,6 +123,13 @@ public void addParams(CommandArguments args) { args.addParams(fieldName); args.add(TEXT); + if (indexMissing) { + args.add(INDEXMISSING); + } + if (indexEmpty) { + args.add(INDEXEMPTY); + } + if (weight != null) { args.add(WEIGHT).add(weight); } diff --git a/src/main/java/redis/clients/jedis/search/schemafields/VectorField.java b/src/main/java/redis/clients/jedis/search/schemafields/VectorField.java index 02287a5be3..f550f66e77 100644 --- a/src/main/java/redis/clients/jedis/search/schemafields/VectorField.java +++ b/src/main/java/redis/clients/jedis/search/schemafields/VectorField.java @@ -1,5 +1,6 @@ package redis.clients.jedis.search.schemafields; +import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.INDEXMISSING; import static redis.clients.jedis.search.SearchProtocol.SearchKeyword.VECTOR; import java.util.LinkedHashMap; @@ -17,6 +18,9 @@ public enum VectorAlgorithm { private final VectorAlgorithm algorithm; private final Map attributes; + private boolean indexMissing; + // private boolean noIndex; // throws Field `NOINDEX` does not have a type + public VectorField(String fieldName, VectorAlgorithm algorithm, Map attributes) { super(fieldName); this.algorithm = algorithm; @@ -35,14 +39,23 @@ public VectorField as(String attribute) { return this; } + public VectorField indexMissing() { + this.indexMissing = true; + return this; + } + @Override public void addParams(CommandArguments args) { args.addParams(fieldName); args.add(VECTOR); args.add(algorithm); - args.add(attributes.size() * 2); + args.add(attributes.size() << 1); attributes.forEach((name, value) -> args.add(name).add(value)); + + if (indexMissing) { + args.add(INDEXMISSING); + } } public static Builder builder() { diff --git a/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java b/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java index cc24fc21de..222d8248d7 100644 --- a/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java +++ b/src/test/java/redis/clients/jedis/modules/search/SearchWithParamsTest.java @@ -28,6 +28,7 @@ import redis.clients.jedis.json.Path; import redis.clients.jedis.search.*; import redis.clients.jedis.search.schemafields.*; +import redis.clients.jedis.search.schemafields.GeoShapeField.CoordinateSystem; import redis.clients.jedis.search.schemafields.VectorField.VectorAlgorithm; import redis.clients.jedis.modules.RedisModuleCommandsTestBase; @@ -194,19 +195,19 @@ public void search() { addDocument(String.format("doc%d", i), fields); } - SearchResult res = client.ftSearch(index, "hello world", + SearchResult result = client.ftSearch(index, "hello world", FTSearchParams.searchParams().limit(0, 5).withScores()); - assertEquals(100, res.getTotalResults()); - assertEquals(5, res.getDocuments().size()); - for (Document d : res.getDocuments()) { + assertEquals(100, result.getTotalResults()); + assertEquals(5, result.getDocuments().size()); + for (Document d : result.getDocuments()) { assertTrue(d.getId().startsWith("doc")); assertTrue(d.getScore() < 100); } client.del("doc0"); - res = client.ftSearch(index, "hello world"); - assertEquals(99, res.getTotalResults()); + result = client.ftSearch(index, "hello world"); + assertEquals(99, result.getTotalResults()); assertEquals("OK", client.ftDropIndex(index)); try { @@ -216,6 +217,57 @@ public void search() { } } + @Test + public void textFieldParams() { + assertOK(client.ftCreate("testindex", TextField.of("title").indexMissing().indexEmpty() + .weight(2.5).noStem().phonetic("dm:en").withSuffixTrie().sortable())); + + assertOK(client.ftCreate("testunfindex", TextField.of("title").indexMissing().indexEmpty() + .weight(2.5).noStem().phonetic("dm:en").withSuffixTrie().sortableUNF())); + + assertOK(client.ftCreate("testnoindex", TextField.of("title").sortable().noIndex())); + + assertOK(client.ftCreate("testunfnoindex", TextField.of("title").sortableUNF().noIndex())); + } + + @Test + public void searchTextFieldsCondition() { + assertOK(client.ftCreate(index, FTCreateParams.createParams(), TextField.of("title"), + TextField.of("body").indexMissing().indexEmpty())); + + Map regular = new HashMap<>(); + regular.put("title", "hello world"); + regular.put("body", "lorem ipsum"); + client.hset("regular-doc", regular); + + Map empty = new HashMap<>(); + empty.put("title", "hello world"); + empty.put("body", ""); + client.hset("empty-doc", empty); + + Map missing = new HashMap<>(); + missing.put("title", "hello world"); + client.hset("missing-doc", missing); + + SearchResult result = client.ftSearch(index, "", FTSearchParams.searchParams().dialect(2)); + assertEquals(0, result.getTotalResults()); + assertEquals(0, result.getDocuments().size()); + + result = client.ftSearch(index, "*", FTSearchParams.searchParams().dialect(2)); + assertEquals(3, result.getTotalResults()); + assertEquals(3, result.getDocuments().size()); + + result = client.ftSearch(index, "@body:''", FTSearchParams.searchParams().dialect(2)); + assertEquals(1, result.getTotalResults()); + assertEquals(1, result.getDocuments().size()); + assertEquals("empty-doc", result.getDocuments().get(0).getId()); + + result = client.ftSearch(index, "ismissing(@body)", FTSearchParams.searchParams().dialect(2)); + assertEquals(1, result.getTotalResults()); + assertEquals(1, result.getDocuments().size()); + assertEquals("missing-doc", result.getDocuments().get(0).getId()); + } + @Test public void numericFilter() { assertOK(client.ftCreate(index, TextField.of("title"), NumericField.of("price"))); @@ -268,7 +320,15 @@ public void numericFilter() { .filter("price", Double.NEGATIVE_INFINITY, 10)); assertEquals(11, res.getTotalResults()); assertEquals(10, res.getDocuments().size()); + } + @Test + public void numericFieldParams() { + assertOK(client.ftCreate("testindex", TextField.of("title"), + NumericField.of("price").as("px").indexMissing().sortable())); + + assertOK(client.ftCreate("testnoindex", TextField.of("title"), + NumericField.of("price").as("px").sortable().noIndex())); } @Test @@ -349,12 +409,19 @@ public void geoFilterAndGeoCoordinateObject() { assertEquals(2, res.getTotalResults()); } + @Test + public void geoFieldParams() { + assertOK(client.ftCreate("testindex", TextField.of("title"), GeoField.of("location").as("loc").indexMissing().sortable())); + + assertOK(client.ftCreate("testnoindex", TextField.of("title"), GeoField.of("location").as("loc").sortable().noIndex())); + } + @Test public void geoShapeFilterSpherical() throws ParseException { final WKTReader reader = new WKTReader(); final GeometryFactory factory = new GeometryFactory(); - assertOK(client.ftCreate(index, GeoShapeField.of("geom", GeoShapeField.CoordinateSystem.SPHERICAL))); + assertOK(client.ftCreate(index, GeoShapeField.of("geom", CoordinateSystem.SPHERICAL))); // polygon type final Polygon small = factory.createPolygon(new Coordinate[]{new Coordinate(34.9001, 29.7001), @@ -403,7 +470,7 @@ public void geoShapeFilterFlat() throws ParseException { final WKTReader reader = new WKTReader(); final GeometryFactory factory = new GeometryFactory(); - assertOK(client.ftCreate(index, GeoShapeField.of("geom", GeoShapeField.CoordinateSystem.FLAT))); + assertOK(client.ftCreate(index, GeoShapeField.of("geom", CoordinateSystem.FLAT))); // polygon type final Polygon small = factory.createPolygon(new Coordinate[]{new Coordinate(20, 20), @@ -459,6 +526,13 @@ public void geoShapeFilterFlat() throws ParseException { assertEquals(2, result.getDocuments().size()); } + @Test + public void geoShapeFieldParams() { + assertOK(client.ftCreate("testindex", GeoShapeField.of("geometry", CoordinateSystem.SPHERICAL).as("geom").indexMissing())); + + assertOK(client.ftCreate("testnoindex", GeoShapeField.of("geometry", CoordinateSystem.SPHERICAL).as("geom").noIndex())); + } + @Test public void testQueryFlags() { assertOK(client.ftCreate(index, TextField.of("title"))); @@ -871,6 +945,23 @@ public void caseSensitiveTagField() { assertEquals(1, client.ftSearch(index, "hello").getTotalResults()); } + @Test + public void tagFieldParams() { + assertOK(client.ftCreate("testindex", TextField.of("title"), + TagField.of("category").as("cat").indexMissing().indexEmpty() + .separator(',').caseSensitive().withSuffixTrie().sortable())); + + assertOK(client.ftCreate("testunfindex", TextField.of("title"), + TagField.of("category").as("cat").indexMissing().indexEmpty() + .separator(',').caseSensitive().withSuffixTrie().sortableUNF())); + + assertOK(client.ftCreate("testnoindex", TextField.of("title"), + TagField.of("category").as("cat").sortable().noIndex())); + + assertOK(client.ftCreate("testunfnoindex", TextField.of("title"), + TagField.of("category").as("cat").sortableUNF().noIndex())); + } + @Test public void testReturnFields() { assertOK(client.ftCreate(index, TextField.of("field1"), TextField.of("field2"))); @@ -1038,14 +1129,14 @@ public void inOrder() { } @Test - public void testHNSWVVectorSimilarity() { + public void testHNSWVectorSimilarity() { Map attr = new HashMap<>(); attr.put("TYPE", "FLOAT32"); attr.put("DIM", 2); attr.put("DISTANCE_METRIC", "L2"); assertOK(client.ftCreate(index, VectorField.builder().fieldName("v") - .algorithm(VectorField.VectorAlgorithm.HNSW).attributes(attr).build())); + .algorithm(VectorAlgorithm.HNSW).attributes(attr).build())); client.hset("a", "v", "aaaaaaaa"); client.hset("b", "v", "aaaabaaa"); @@ -1065,7 +1156,7 @@ public void testHNSWVVectorSimilarity() { public void testFlatVectorSimilarity() { assertOK(client.ftCreate(index, VectorField.builder().fieldName("v") - .algorithm(VectorField.VectorAlgorithm.FLAT) + .algorithm(VectorAlgorithm.FLAT) .addAttribute("TYPE", "FLOAT32") .addAttribute("DIM", 2) .addAttribute("DISTANCE_METRIC", "L2") @@ -1087,11 +1178,24 @@ public void testFlatVectorSimilarity() { assertEquals("0", doc1.get("__v_score")); } + @Test + public void vectorFieldParams() { + Map attr = new HashMap<>(); + attr.put("TYPE", "FLOAT32"); + attr.put("DIM", 2); + attr.put("DISTANCE_METRIC", "L2"); + + assertOK(client.ftCreate("testindex", new VectorField("vector", VectorAlgorithm.HNSW, attr).as("vec").indexMissing())); + + // assertOK(client.ftCreate("testnoindex", new VectorField("vector", VectorAlgorithm.HNSW, attr).as("vec").noIndex())); + // throws Field `NOINDEX` does not have a type + } + @Test public void float16StorageType() { assertOK(client.ftCreate(index, VectorField.builder().fieldName("v") - .algorithm(VectorField.VectorAlgorithm.HNSW) + .algorithm(VectorAlgorithm.HNSW) .addAttribute("TYPE", "FLOAT16") .addAttribute("DIM", 4) .addAttribute("DISTANCE_METRIC", "L2") @@ -1102,7 +1206,7 @@ public void float16StorageType() { public void bfloat16StorageType() { assertOK(client.ftCreate(index, VectorField.builder().fieldName("v") - .algorithm(VectorField.VectorAlgorithm.HNSW) + .algorithm(VectorAlgorithm.HNSW) .addAttribute("TYPE", "BFLOAT16") .addAttribute("DIM", 4) .addAttribute("DISTANCE_METRIC", "L2")