diff --git a/core/src/main/java/com/arangodb/ArangoCollection.java b/core/src/main/java/com/arangodb/ArangoCollection.java index 302335607..f38fffd5a 100644 --- a/core/src/main/java/com/arangodb/ArangoCollection.java +++ b/core/src/main/java/com/arangodb/ArangoCollection.java @@ -665,9 +665,36 @@ MultiDocumentEntity> deleteDocuments( * @return information about the index * @see API Documentation * @since ArangoDB 3.9 + * @deprecated since ArangoDB 3.12, use {@link #ensureMDIndex(Iterable, MDIndexOptions)} or + * {@link #ensureMDPrefixedIndex(Iterable, MDPrefixedIndexOptions)} instead. */ + @Deprecated IndexEntity ensureZKDIndex(Iterable fields, ZKDIndexOptions options); + /** + * Creates a multi-dimensional index for the collection, if it does not already exist. + * + * @param fields A list of attribute names used for each dimension + * @param options Additional options, can be null. + * + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.12 + */ + IndexEntity ensureMDIndex(Iterable fields, MDIndexOptions options); + + /** + * Creates a multi-dimensional prefixed index for the collection, if it does not already exist. + * + * @param fields A list of attribute names used for each dimension + * @param options Additional options, cannot be null. + * + * @return information about the index + * @see API Documentation + * @since ArangoDB 3.12 + */ + IndexEntity ensureMDPrefixedIndex(Iterable fields, MDPrefixedIndexOptions options); + /** * Creates an inverted index for the collection, if it does not already exist. * diff --git a/core/src/main/java/com/arangodb/ArangoCollectionAsync.java b/core/src/main/java/com/arangodb/ArangoCollectionAsync.java index f3dd03484..8de03b874 100644 --- a/core/src/main/java/com/arangodb/ArangoCollectionAsync.java +++ b/core/src/main/java/com/arangodb/ArangoCollectionAsync.java @@ -305,9 +305,23 @@ CompletableFuture>> deleteDocume /** * Asynchronous version of {@link ArangoCollection#ensureZKDIndex(Iterable, ZKDIndexOptions)} + * + * @deprecated since ArangoDB 3.12, use {@link #ensureMDIndex(Iterable, MDIndexOptions)} or + * {@link #ensureMDPrefixedIndex(Iterable, MDPrefixedIndexOptions)} instead. */ + @Deprecated CompletableFuture ensureZKDIndex(Iterable fields, ZKDIndexOptions options); + /** + * Asynchronous version of {@link ArangoCollection#ensureMDIndex(Iterable, MDIndexOptions)} + */ + CompletableFuture ensureMDIndex(Iterable fields, MDIndexOptions options); + + /** + * Asynchronous version of {@link ArangoCollection#ensureMDPrefixedIndex(Iterable, MDPrefixedIndexOptions)} + */ + CompletableFuture ensureMDPrefixedIndex(Iterable fields, MDPrefixedIndexOptions options); + /** * Asynchronous version of {@link ArangoCollection#ensureInvertedIndex(InvertedIndexOptions)} */ diff --git a/core/src/main/java/com/arangodb/entity/IndexEntity.java b/core/src/main/java/com/arangodb/entity/IndexEntity.java index 06bf9c65f..b488845b7 100644 --- a/core/src/main/java/com/arangodb/entity/IndexEntity.java +++ b/core/src/main/java/com/arangodb/entity/IndexEntity.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import com.arangodb.model.MDIFieldValueTypes; + import java.util.Collection; /** @@ -45,6 +47,8 @@ public final class IndexEntity { private Boolean cacheEnabled; private Collection storedValues; private Boolean legacyPolygons; + private MDIFieldValueTypes fieldValueTypes; + private Collection prefixFields; public IndexEntity() { super(); @@ -122,4 +126,11 @@ public Boolean getLegacyPolygons() { return legacyPolygons; } + public MDIFieldValueTypes getFieldValueTypes() { + return fieldValueTypes; + } + + public Collection getPrefixFields() { + return prefixFields; + } } diff --git a/core/src/main/java/com/arangodb/entity/IndexType.java b/core/src/main/java/com/arangodb/entity/IndexType.java index d3303b5f5..922a6c865 100644 --- a/core/src/main/java/com/arangodb/entity/IndexType.java +++ b/core/src/main/java/com/arangodb/entity/IndexType.java @@ -20,6 +20,8 @@ package com.arangodb.entity; +import com.fasterxml.jackson.annotation.JsonProperty; + /** * @author Mark Vollmary * @author Heiko Kernbach @@ -52,6 +54,21 @@ public enum IndexType { zkd, + /** + * Multi Dimensional Index + * @see Ref Doc + * @since ArangoDB 3.12 + */ + mdi, + + /** + * Multi Dimensional Prefixed Index + * @see Ref Doc + * @since ArangoDB 3.12 + */ + @JsonProperty("mdi-prefixed") + mdiPrefixed, + /** * @since ArangoDB 3.10 */ diff --git a/core/src/main/java/com/arangodb/internal/ArangoCollectionAsyncImpl.java b/core/src/main/java/com/arangodb/internal/ArangoCollectionAsyncImpl.java index a7b62fa74..17fb9a8b2 100644 --- a/core/src/main/java/com/arangodb/internal/ArangoCollectionAsyncImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoCollectionAsyncImpl.java @@ -387,6 +387,16 @@ public CompletableFuture ensureZKDIndex(final Iterable fiel return executorAsync().execute(() -> createZKDIndexRequest(fields, options), IndexEntity.class); } + @Override + public CompletableFuture ensureMDIndex(final Iterable fields, final MDIndexOptions options) { + return executorAsync().execute(() -> createMDIndexRequest(fields, options), IndexEntity.class); + } + + @Override + public CompletableFuture ensureMDPrefixedIndex(final Iterable fields, final MDPrefixedIndexOptions options) { + return executorAsync().execute(() -> createMDIndexRequest(fields, options), IndexEntity.class); + } + @Override public CompletableFuture> getIndexes() { return executorAsync().execute(this::getIndexesRequest, getIndexesResponseDeserializer()); diff --git a/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java b/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java index 56da41518..40cb4276e 100644 --- a/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java +++ b/core/src/main/java/com/arangodb/internal/ArangoCollectionImpl.java @@ -378,6 +378,16 @@ public IndexEntity ensureZKDIndex(final Iterable fields, final ZKDIndexO return executorSync().execute(createZKDIndexRequest(fields, options), IndexEntity.class); } + @Override + public IndexEntity ensureMDIndex(final Iterable fields, final MDIndexOptions options) { + return executorSync().execute(createMDIndexRequest(fields, options), IndexEntity.class); + } + + @Override + public IndexEntity ensureMDPrefixedIndex(final Iterable fields, final MDPrefixedIndexOptions options) { + return executorSync().execute(createMDIndexRequest(fields, options), IndexEntity.class); + } + @Override public Collection getIndexes() { return executorSync().execute(getIndexesRequest(), getIndexesResponseDeserializer()); diff --git a/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java index 3d89ca5b5..ba43bb207 100644 --- a/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/core/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -475,6 +475,15 @@ protected InternalRequest createZKDIndexRequest( return request; } + protected InternalRequest createMDIndexRequest( + final Iterable fields, final AbstractMDIndexOptions options) { + final InternalRequest request = request(dbName, RequestType.POST, PATH_API_INDEX); + request.putQueryParam(COLLECTION, name); + AbstractMDIndexOptions opts = options != null ? options : new MDIndexOptions().fieldValueTypes(MDIFieldValueTypes.DOUBLE); + request.setBody(getSerde().serialize(OptionsBuilder.build(opts, fields))); + return request; + } + protected InternalRequest getIndexesRequest() { final InternalRequest request = request(dbName, RequestType.GET, PATH_API_INDEX); request.putQueryParam(COLLECTION, name); diff --git a/core/src/main/java/com/arangodb/model/AbstractMDIndexOptions.java b/core/src/main/java/com/arangodb/model/AbstractMDIndexOptions.java new file mode 100644 index 000000000..93d379c2f --- /dev/null +++ b/core/src/main/java/com/arangodb/model/AbstractMDIndexOptions.java @@ -0,0 +1,143 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.arch.NoRawTypesInspection; +import com.arangodb.entity.IndexType; + + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.12 + */ +@NoRawTypesInspection +public abstract class AbstractMDIndexOptions> extends IndexOptions { + + private Iterable fields; + private Boolean unique; + private MDIFieldValueTypes fieldValueTypes; + private Boolean estimates; + private Boolean sparse; + private Iterable storedValues; + + + public AbstractMDIndexOptions() { + super(); + } + + public abstract IndexType getType(); + + public Iterable getFields() { + return fields; + } + + /** + * @param fields A list of attribute names used for each dimension. Array expansions are not allowed. + * @return options + */ + T fields(final Iterable fields) { + this.fields = fields; + return getThis(); + } + + public Boolean getUnique() { + return unique; + } + + /** + * @param unique if true, then create a unique index + * @return options + */ + public T unique(final Boolean unique) { + this.unique = unique; + return getThis(); + } + + public MDIFieldValueTypes getFieldValueTypes() { + return fieldValueTypes; + } + + /** + * @param fieldValueTypes must be {@link MDIFieldValueTypes#DOUBLE}, currently only doubles are supported as values. + * @return options + */ + public T fieldValueTypes(final MDIFieldValueTypes fieldValueTypes) { + this.fieldValueTypes = fieldValueTypes; + return getThis(); + } + + public Boolean getEstimates() { + return estimates; + } + + /** + * @param estimates controls whether index selectivity estimates are maintained for the index. Not maintaining index + * selectivity estimates can have a slightly positive impact on write performance. + * The downside of turning off index selectivity estimates is that the query optimizer is not able + * to determine the usefulness of different competing indexes in AQL queries when there are + * multiple candidate indexes to choose from. + * The estimates attribute is optional and defaults to true if not set. + * It cannot be disabled for non-unique multi-dimensional indexes because they have a fixed + * selectivity estimate of 1. + * @return options + */ + public T estimates(final Boolean estimates) { + this.estimates = estimates; + return getThis(); + } + + public Boolean getSparse() { + return sparse; + } + + /** + * @param sparse if true, then create a sparse index + * @return options + */ + public T sparse(final Boolean sparse) { + this.sparse = sparse; + return getThis(); + } + + public Iterable getStoredValues() { + return storedValues; + } + + /** + * @param storedValues can contain an array of paths to additional attributes to store in the index. + * These additional attributes cannot be used for index lookups or for sorting, but they can be + * used for projections. This allows an index to fully cover more queries and avoid extra + * document lookups. + * You can have the same attributes in storedValues and fields as the attributes in fields + * cannot be used for projections, but you can also store additional attributes that are not + * listed in fields. + * Attributes in storedValues cannot overlap with the attributes specified in prefixFields. + * Non-existing attributes are stored as null values inside storedValues. + * The maximum number of attributes in storedValues is 32. + * @return options + */ + public T storedValues(final Iterable storedValues) { + this.storedValues = storedValues; + return getThis(); + } + +} diff --git a/core/src/main/java/com/arangodb/model/MDIFieldValueTypes.java b/core/src/main/java/com/arangodb/model/MDIFieldValueTypes.java new file mode 100644 index 000000000..1bf3fcb10 --- /dev/null +++ b/core/src/main/java/com/arangodb/model/MDIFieldValueTypes.java @@ -0,0 +1,8 @@ +package com.arangodb.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum MDIFieldValueTypes { + @JsonProperty("double") + DOUBLE +} diff --git a/core/src/main/java/com/arangodb/model/MDIndexOptions.java b/core/src/main/java/com/arangodb/model/MDIndexOptions.java new file mode 100644 index 000000000..4ba8d5242 --- /dev/null +++ b/core/src/main/java/com/arangodb/model/MDIndexOptions.java @@ -0,0 +1,47 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.12 + */ +public final class MDIndexOptions extends AbstractMDIndexOptions { + + public MDIndexOptions() { + super(); + } + + @Override + public IndexType getType() { + return IndexType.mdi; + } + + @Override + MDIndexOptions getThis() { + return this; + } + +} diff --git a/core/src/main/java/com/arangodb/model/MDPrefixedIndexOptions.java b/core/src/main/java/com/arangodb/model/MDPrefixedIndexOptions.java new file mode 100644 index 000000000..76f040a1a --- /dev/null +++ b/core/src/main/java/com/arangodb/model/MDPrefixedIndexOptions.java @@ -0,0 +1,62 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb.model; + +import com.arangodb.entity.IndexType; + + +/** + * @author Michele Rastelli + * @see API Documentation + * @since ArangoDB 3.12 + */ +public final class MDPrefixedIndexOptions extends AbstractMDIndexOptions { + + private Iterable prefixFields; + + public MDPrefixedIndexOptions() { + super(); + } + + public Iterable getPrefixFields() { + return prefixFields; + } + + /** + * @param prefixFields An array of attribute names used as search prefix. Array expansions are not allowed. + * @return options + */ + public MDPrefixedIndexOptions prefixFields(final Iterable prefixFields) { + this.prefixFields = prefixFields; + return this; + } + + @Override + public IndexType getType() { + return IndexType.mdiPrefixed; + } + + @Override + MDPrefixedIndexOptions getThis() { + return this; + } + +} diff --git a/core/src/main/java/com/arangodb/model/OptionsBuilder.java b/core/src/main/java/com/arangodb/model/OptionsBuilder.java index 216d9b6e4..11ea5b0ab 100644 --- a/core/src/main/java/com/arangodb/model/OptionsBuilder.java +++ b/core/src/main/java/com/arangodb/model/OptionsBuilder.java @@ -62,6 +62,10 @@ public static ZKDIndexOptions build(final ZKDIndexOptions options, final Iterabl return options.fields(fields); } + public static AbstractMDIndexOptions build(final AbstractMDIndexOptions options, final Iterable fields) { + return options.fields(fields); + } + public static CollectionCreateOptions build(final CollectionCreateOptions options, final String name) { return options.name(name); } diff --git a/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java b/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java index e4742e8ed..b5d9041b9 100644 --- a/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java +++ b/core/src/main/java/com/arangodb/model/ZKDIndexOptions.java @@ -27,7 +27,9 @@ * @author Michele Rastelli * @see API Documentation * @since ArangoDB 3.9 + * @deprecated since ArangoDB 3.12, use {@link MDIndexOptions} instead. */ +@Deprecated public final class ZKDIndexOptions extends IndexOptions { final IndexType type = IndexType.zkd; diff --git a/driver/src/test/java/com/arangodb/ArangoCollectionAsyncTest.java b/driver/src/test/java/com/arangodb/ArangoCollectionAsyncTest.java index e2c3ca18d..d97300619 100644 --- a/driver/src/test/java/com/arangodb/ArangoCollectionAsyncTest.java +++ b/driver/src/test/java/com/arangodb/ArangoCollectionAsyncTest.java @@ -1615,6 +1615,98 @@ void createZKDIndexWithOptions(ArangoCollectionAsync collection) throws Executio collection.deleteIndex(indexResult.getId()).get(); } + @ParameterizedTest + @MethodSource("asyncCols") + void createMDIndex(ArangoCollectionAsync collection) throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 12)); + collection.truncate().get(); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final IndexEntity indexResult = collection.ensureMDIndex(Arrays.asList(f1, f2), null).get(); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1, f2); + assertThat(indexResult.getFieldValueTypes()).isEqualTo(MDIFieldValueTypes.DOUBLE); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.mdi); + assertThat(indexResult.getUnique()).isFalse(); + collection.deleteIndex(indexResult.getId()).get(); + } + + @ParameterizedTest + @MethodSource("asyncCols") + void createMDIndexWithOptions(ArangoCollectionAsync collection) throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 12)); + collection.truncate().get(); + + String name = "MDIndex-" + rnd(); + final MDIndexOptions options = new MDIndexOptions() + .name(name) + .unique(false) + .fieldValueTypes(MDIFieldValueTypes.DOUBLE) + .estimates(false) + .sparse(true) + .storedValues(Arrays.asList("v1", "v2")); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final IndexEntity indexResult = collection.ensureMDIndex(Arrays.asList(f1, f2), options).get(); + assertThat(indexResult.getType()).isEqualTo(IndexType.mdi); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getName()).isEqualTo(name); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getEstimates()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); + assertThat(indexResult.getFields()).contains(f1, f2); + assertThat(indexResult.getFieldValueTypes()).isEqualTo(MDIFieldValueTypes.DOUBLE); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + collection.deleteIndex(indexResult.getId()).get(); + } + + @ParameterizedTest + @MethodSource("asyncCols") + void createMDPrefixedIndexWithOptions(ArangoCollectionAsync collection) throws ExecutionException, InterruptedException { + assumeTrue(isAtLeastVersion(3, 12)); + collection.truncate().get(); + + String name = "MDPrefixedIndex-" + rnd(); + final MDPrefixedIndexOptions options = new MDPrefixedIndexOptions() + .name(name) + .unique(false) + .fieldValueTypes(MDIFieldValueTypes.DOUBLE) + .estimates(false) + .sparse(true) + .storedValues(Arrays.asList("v1", "v2")) + .prefixFields(Arrays.asList("p1", "p2")); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final IndexEntity indexResult = collection.ensureMDPrefixedIndex(Arrays.asList(f1, f2), options).get(); + assertThat(indexResult.getType()).isEqualTo(IndexType.mdiPrefixed); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getName()).isEqualTo(name); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getEstimates()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); + assertThat(indexResult.getFields()).contains(f1, f2); + assertThat(indexResult.getFieldValueTypes()).isEqualTo(MDIFieldValueTypes.DOUBLE); + assertThat(indexResult.getPrefixFields()).contains("p1", "p2"); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + collection.deleteIndex(indexResult.getId()).get(); + } + @ParameterizedTest @MethodSource("asyncCols") void indexEstimates(ArangoCollectionAsync collection) throws ExecutionException, InterruptedException { diff --git a/driver/src/test/java/com/arangodb/ArangoCollectionTest.java b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java index 8d1087992..092f1e1d3 100644 --- a/driver/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/driver/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -1640,6 +1640,98 @@ void createZKDIndexWithOptions(ArangoCollection collection) { collection.deleteIndex(indexResult.getId()); } + @ParameterizedTest + @MethodSource("cols") + void createMDIndex(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 12)); + collection.truncate(); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final IndexEntity indexResult = collection.ensureMDIndex(Arrays.asList(f1, f2), null); + assertThat(indexResult).isNotNull(); + assertThat(indexResult.getConstraint()).isNull(); + assertThat(indexResult.getFields()).contains(f1, f2); + assertThat(indexResult.getFieldValueTypes()).isEqualTo(MDIFieldValueTypes.DOUBLE); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + assertThat(indexResult.getMinLength()).isNull(); + assertThat(indexResult.getType()).isEqualTo(IndexType.mdi); + assertThat(indexResult.getUnique()).isFalse(); + collection.deleteIndex(indexResult.getId()); + } + + @ParameterizedTest + @MethodSource("cols") + void createMDIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 12)); + collection.truncate(); + + String name = "MDIndex-" + rnd(); + final MDIndexOptions options = new MDIndexOptions() + .name(name) + .unique(false) + .fieldValueTypes(MDIFieldValueTypes.DOUBLE) + .estimates(false) + .sparse(true) + .storedValues(Arrays.asList("v1", "v2")); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final IndexEntity indexResult = collection.ensureMDIndex(Arrays.asList(f1, f2), options); + assertThat(indexResult.getType()).isEqualTo(IndexType.mdi); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getName()).isEqualTo(name); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getEstimates()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); + assertThat(indexResult.getFields()).contains(f1, f2); + assertThat(indexResult.getFieldValueTypes()).isEqualTo(MDIFieldValueTypes.DOUBLE); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + collection.deleteIndex(indexResult.getId()); + } + + @ParameterizedTest + @MethodSource("cols") + void createMDPrefixedIndexWithOptions(ArangoCollection collection) { + assumeTrue(isAtLeastVersion(3, 12)); + collection.truncate(); + + String name = "MDPrefixedIndex-" + rnd(); + final MDPrefixedIndexOptions options = new MDPrefixedIndexOptions() + .name(name) + .unique(false) + .fieldValueTypes(MDIFieldValueTypes.DOUBLE) + .estimates(false) + .sparse(true) + .storedValues(Arrays.asList("v1", "v2")) + .prefixFields(Arrays.asList("p1", "p2")); + + String f1 = "field-" + rnd(); + String f2 = "field-" + rnd(); + + final IndexEntity indexResult = collection.ensureMDPrefixedIndex(Arrays.asList(f1, f2), options); + assertThat(indexResult.getType()).isEqualTo(IndexType.mdiPrefixed); + assertThat(indexResult.getId()).startsWith(COLLECTION_NAME); + assertThat(indexResult.getName()).isEqualTo(name); + assertThat(indexResult.getUnique()).isFalse(); + assertThat(indexResult.getEstimates()).isFalse(); + assertThat(indexResult.getSparse()).isTrue(); + assertThat(indexResult.getStoredValues()) + .hasSize(2) + .contains("v1", "v2"); + assertThat(indexResult.getFields()).contains(f1, f2); + assertThat(indexResult.getFieldValueTypes()).isEqualTo(MDIFieldValueTypes.DOUBLE); + assertThat(indexResult.getPrefixFields()).contains("p1", "p2"); + assertThat(indexResult.getIsNewlyCreated()).isTrue(); + collection.deleteIndex(indexResult.getId()); + } + @ParameterizedTest @MethodSource("cols") void indexEstimates(ArangoCollection collection) {