diff --git a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java index a0ef88451..54a152ff3 100644 --- a/src/main/java/com/arangodb/entity/InvertedIndexEntity.java +++ b/src/main/java/com/arangodb/entity/InvertedIndexEntity.java @@ -45,6 +45,7 @@ public class InvertedIndexEntity implements Entity { private Collection fields; private Boolean searchField; private Collection storedValues; + private Collection optimizeTopK; private InvertedIndexPrimarySort primarySort; private String analyzer; private Set features; @@ -104,6 +105,10 @@ public Collection getStoredValues() { return storedValues; } + public Collection getOptimizeTopK() { + return optimizeTopK; + } + public InvertedIndexPrimarySort getPrimarySort() { return primarySort; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java index 8bf5d0172..1dd7b22ea 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchProperties.java @@ -42,6 +42,7 @@ public class ArangoSearchProperties { private final Collection links; private ArangoSearchCompression primarySortCompression; private final Collection storedValues; + private final Collection optimizeTopK; private Boolean primarySortCache; private Boolean primaryKeyCache; @@ -50,6 +51,7 @@ public ArangoSearchProperties() { links = new ArrayList<>(); primarySorts = new ArrayList<>(); storedValues = new ArrayList<>(); + optimizeTopK = new ArrayList<>(); } public Long getCommitIntervalMsec() { @@ -127,6 +129,18 @@ public void addStoredValues(final StoredValue... storedValues) { this.storedValues.addAll(Arrays.asList(storedValues)); } + /** + * @return An array of strings defining optimized sort expressions. + * @since ArangoDB 3.11, Enterprise Edition only + */ + public Collection getOptimizeTopK() { + return optimizeTopK; + } + + public void addOptimizeTopK(final String... optimizeTopK) { + this.optimizeTopK.addAll(Arrays.asList(optimizeTopK)); + } + public Boolean getPrimarySortCache() { return primarySortCache; } diff --git a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java index f6cda4c85..8216bcd5d 100644 --- a/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java +++ b/src/main/java/com/arangodb/entity/arangosearch/ArangoSearchPropertiesEntity.java @@ -116,6 +116,14 @@ public Collection getStoredValues() { return properties.getStoredValues(); } + /** + * @return An array of strings defining optimized sort expressions. + * @since ArangoDB 3.11, Enterprise Edition only + */ + public Collection getOptimizeTopK() { + return properties.getOptimizeTopK(); + } + /** * @return If you enable this option, then the primary sort columns are always cached in memory. This can improve * the performance of queries that utilize the primary sort order. Otherwise, these values are memory-mapped and it diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java index 4f64a38a9..3926d370b 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackDeserializers.java @@ -276,6 +276,15 @@ public class VPackDeserializers { properties.addStoredValues(sv); } + final VPackSlice optimizeTopK = vpack.get("optimizeTopK"); + if (optimizeTopK.isArray()) { + final Iterator optimizeTopKIterator = optimizeTopK.arrayIterator(); + while (optimizeTopKIterator.hasNext()) { + String o = context.deserialize(optimizeTopKIterator.next(), String.class); + properties.addOptimizeTopK(o); + } + } + return properties; }; diff --git a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java index ec55012d9..50abcb205 100644 --- a/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java +++ b/src/main/java/com/arangodb/internal/velocypack/VPackSerializers.java @@ -239,6 +239,15 @@ public class VPackSerializers { builder.close(); // close array } + final Collection optimizeTopK = value.getOptimizeTopK(); + if (!optimizeTopK.isEmpty()) { + builder.add("optimizeTopK", ValueType.ARRAY); // open array + for (final String o : optimizeTopK) { + context.serialize(builder, null, o); + } + builder.close(); // close array + } + }; public static final VPackSerializer SEARCH_ALIAS_PROPERTIES = (builder, attribute, value, context) -> { diff --git a/src/main/java/com/arangodb/model/InvertedIndexOptions.java b/src/main/java/com/arangodb/model/InvertedIndexOptions.java index d444d227c..a206a206e 100644 --- a/src/main/java/com/arangodb/model/InvertedIndexOptions.java +++ b/src/main/java/com/arangodb/model/InvertedIndexOptions.java @@ -38,6 +38,7 @@ public class InvertedIndexOptions extends IndexOptions { private Integer parallelism; private InvertedIndexPrimarySort primarySort; private final Collection storedValues = new ArrayList<>(); + private final Collection optimizeTopK = new ArrayList<>(); private String analyzer; private final Set features = new HashSet<>(); private Boolean includeAllFields; @@ -112,6 +113,20 @@ public InvertedIndexOptions storedValues(StoredValue... storedValues) { return this; } + public Collection getOptimizeTopK() { + return optimizeTopK; + } + + /** + * @param optimizeTopK An array of strings defining sort expressions that you want to optimize. + * @return options + * @since ArangoDB 3.11, Enterprise Edition only + */ + public InvertedIndexOptions optimizeTopK(String... optimizeTopK) { + Collections.addAll(this.optimizeTopK, optimizeTopK); + return this; + } + public String getAnalyzer() { return analyzer; } diff --git a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java index 7f2b7b3c3..4227fac3b 100644 --- a/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java +++ b/src/main/java/com/arangodb/model/arangosearch/ArangoSearchCreateOptions.java @@ -134,6 +134,15 @@ public ArangoSearchCreateOptions storedValues(final StoredValue... storedValues) return this; } + /** + * @param optimizeTopK An array of strings defining sort expressions that you want to optimize. + * @return options + * @since ArangoDB 3.11, Enterprise Edition only + */ + public ArangoSearchCreateOptions optimizeTopK(final String... optimizeTopK) { + properties.addOptimizeTopK(optimizeTopK); + return this; + } /** * @param primarySortCache If you enable this option, then the primary sort columns are always cached in memory. diff --git a/src/test/java/com/arangodb/ArangoSearchTest.java b/src/test/java/com/arangodb/ArangoSearchTest.java index bd180de91..a2faa6351 100644 --- a/src/test/java/com/arangodb/ArangoSearchTest.java +++ b/src/test/java/com/arangodb/ArangoSearchTest.java @@ -931,6 +931,8 @@ void arangoSearchOptions(ArangoDatabase db) { .primaryKeyCache(true); StoredValue storedValue = new StoredValue(Arrays.asList("a", "b"), ArangoSearchCompression.none, true); options.storedValues(storedValue); + String[] optimizeTopK = new String[]{"BM25(@doc) DESC", "TFIDF(@doc) DESC"}; + options.optimizeTopK(optimizeTopK); final ArangoSearch view = db.arangoSearch(viewName); view.create(options); @@ -972,6 +974,11 @@ void arangoSearchOptions(ArangoDatabase db) { FieldLink nested = fieldLink.getNested().iterator().next(); assertThat(nested.getName()).isEqualTo("f2"); } + + if (isEnterprise() && isAtLeastVersion(3, 11)) { + assertThat(properties.getOptimizeTopK()).containsExactly(optimizeTopK); + } + } @ParameterizedTest(name = "{index}") diff --git a/src/test/java/com/arangodb/InvertedIndexTest.java b/src/test/java/com/arangodb/InvertedIndexTest.java index 30fb3cbed..4e4b4063a 100644 --- a/src/test/java/com/arangodb/InvertedIndexTest.java +++ b/src/test/java/com/arangodb/InvertedIndexTest.java @@ -93,6 +93,7 @@ private InvertedIndexOptions createOptions(String analyzerName) { .cache(cache) ) .storedValues(new StoredValue(Arrays.asList("f3", "f4"), ArangoSearchCompression.none, cache)) + .optimizeTopK("BM25(@doc) DESC", "TFIDF(@doc) DESC") .analyzer(analyzerName) .features(AnalyzerFeature.position, AnalyzerFeature.frequency) .includeAllFields(false) @@ -144,6 +145,10 @@ private void assertCorrectIndexEntity(InvertedIndexEntity indexResult, InvertedI assertThat(indexResult.getWritebufferSizeMax()).isEqualTo(options.getWritebufferSizeMax()); assertThat(indexResult.getCache()).isEqualTo(options.getCache()); assertThat(indexResult.getPrimaryKeyCache()).isEqualTo(options.getPrimaryKeyCache()); + + if (isEnterprise() && isAtLeastVersion(3, 11)) { + assertThat(indexResult.getOptimizeTopK()).containsExactlyElementsOf(options.getOptimizeTopK()); + } } @ParameterizedTest(name = "{index}")