diff --git a/driver-core/src/main/com/mongodb/client/model/Aggregates.java b/driver-core/src/main/com/mongodb/client/model/Aggregates.java index e451c3560c8..8cd5162a637 100644 --- a/driver-core/src/main/com/mongodb/client/model/Aggregates.java +++ b/driver-core/src/main/com/mongodb/client/model/Aggregates.java @@ -28,8 +28,10 @@ import com.mongodb.client.model.search.SearchOperator; import com.mongodb.client.model.search.SearchOptions; import com.mongodb.client.model.search.TextVectorSearchQuery; +import com.mongodb.client.model.search.VectorSearchNestedOptions; import com.mongodb.client.model.search.VectorSearchOptions; import com.mongodb.client.model.search.VectorSearchQuery; +import com.mongodb.client.model.search.VectorSearchScoreMode; import com.mongodb.lang.Nullable; import org.bson.BsonArray; import org.bson.BsonBoolean; @@ -952,6 +954,13 @@ public static Bson searchMeta(final SearchCollector collector, final SearchOptio * You may use the {@code $meta: "vectorSearchScore"} expression, e.g., via {@link Projections#metaVectorSearchScore(String)}, * to extract the relevance score assigned to each found document. * + *
The {@code path} may reference a nested (embedded) field using dot notation, in which case the + * search is performed against embeddings in the embedded documents. For a nested search, use + * {@link VectorSearchOptions#filter(Bson)} to filter the leaf (embedded) documents, + * {@link VectorSearchOptions#parentFilter(Bson)} to filter the parent documents, and + * {@link VectorSearchOptions#nestedOptions(VectorSearchNestedOptions)} (e.g. + * {@link VectorSearchNestedOptions#scoreMode(VectorSearchScoreMode)}) to control score aggregation.
+ * * @param queryVector The query vector. The number of dimensions must match that of the {@code index}. * @param path The field to be searched. * @param index The name of the index to use. diff --git a/driver-core/src/main/com/mongodb/client/model/search/SearchOptions.java b/driver-core/src/main/com/mongodb/client/model/search/SearchOptions.java index f5cd0261e8f..6fcbb18b181 100644 --- a/driver-core/src/main/com/mongodb/client/model/search/SearchOptions.java +++ b/driver-core/src/main/com/mongodb/client/model/search/SearchOptions.java @@ -54,7 +54,6 @@ public interface SearchOptions extends Bson { * @param option The counting option. * @return A new {@link SearchOptions}. */ - @Beta({Reason.CLIENT, Reason.SERVER}) SearchOptions count(SearchCount option); /** @@ -64,7 +63,6 @@ public interface SearchOptions extends Bson { * @return A new {@link SearchOptions}. * @mongodb.atlas.manual atlas-search/return-stored-source/ Return stored source fields */ - @Beta({Reason.CLIENT, Reason.SERVER}) SearchOptions returnStoredSource(boolean returnStoredSource); /** diff --git a/driver-core/src/main/com/mongodb/client/model/search/VectorSearchConstructibleBson.java b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchConstructibleBson.java index 39a043ca82f..38cf0af0b05 100644 --- a/driver-core/src/main/com/mongodb/client/model/search/VectorSearchConstructibleBson.java +++ b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchConstructibleBson.java @@ -49,6 +49,16 @@ public VectorSearchOptions filter(final Bson filter) { return newAppended("filter", notNull("filter", filter)); } + @Override + public VectorSearchOptions parentFilter(final Bson parentFilter) { + return newAppended("parentFilter", notNull("parentFilter", parentFilter)); + } + + @Override + public VectorSearchOptions nestedOptions(final VectorSearchNestedOptions nestedOptions) { + return newAppended("nestedOptions", notNull("nestedOptions", nestedOptions)); + } + @Override public VectorSearchOptions returnStoredSource(final boolean returnStoredSource) { return newAppended("returnStoredSource", new BsonBoolean(returnStoredSource)); diff --git a/driver-core/src/main/com/mongodb/client/model/search/VectorSearchNestedConstructibleBson.java b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchNestedConstructibleBson.java new file mode 100644 index 00000000000..f0b5966f87d --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchNestedConstructibleBson.java @@ -0,0 +1,56 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +package com.mongodb.client.model.search; + +import com.mongodb.annotations.Immutable; +import com.mongodb.internal.client.model.AbstractConstructibleBson; +import org.bson.BsonDocument; +import org.bson.Document; +import org.bson.conversions.Bson; + +import static com.mongodb.assertions.Assertions.notNull; + +final class VectorSearchNestedConstructibleBson extends AbstractConstructibleBson
+ * Example
+ * The following code creates two functionally equivalent {@link VectorSearchNestedOptions} objects,
+ * though they may not be {@linkplain Object#equals(Object) equal}.
+ *
{@code
+ * VectorSearchNestedOptions options1 = VectorSearchNestedOptions.vectorSearchNestedOptions()
+ * .scoreMode(VectorSearchScoreMode.AVG);
+ * VectorSearchNestedOptions options2 = VectorSearchNestedOptions.vectorSearchNestedOptions()
+ * .option("scoreMode", "avg");
+ * }
+ *
+ * @param name The option name.
+ * @param value The option value.
+ * @return A new {@link VectorSearchNestedOptions}.
+ */
+ VectorSearchNestedOptions option(String name, Object value);
+
+ /**
+ * Returns {@link VectorSearchNestedOptions} that represents server defaults.
+ *
+ * @return {@link VectorSearchNestedOptions} that represents server defaults.
+ */
+ static VectorSearchNestedOptions vectorSearchNestedOptions() {
+ return VectorSearchNestedConstructibleBson.EMPTY_IMMUTABLE;
+ }
+}
diff --git a/driver-core/src/main/com/mongodb/client/model/search/VectorSearchOptions.java b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchOptions.java
index d3bcf3aea46..d52cafd0310 100644
--- a/driver-core/src/main/com/mongodb/client/model/search/VectorSearchOptions.java
+++ b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchOptions.java
@@ -23,6 +23,9 @@
/**
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
*
+ * This includes options for searching against nested (embedded) embeddings and arrays of embeddings, + * via {@link #parentFilter(Bson)} and {@link #nestedOptions(VectorSearchNestedOptions)}.
+ * * @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions) * @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch * @mongodb.server.release 6.0.11 @@ -41,6 +44,41 @@ public interface VectorSearchOptions extends Bson { */ VectorSearchOptions filter(Bson filter); + /** + * Creates a new {@link VectorSearchOptions} with the parent filter specified. + * + *Applies only when searching against a nested (embedded) field: this filter is applied to the + * parent (root) documents, while {@link #filter(Bson)} is applied to the leaf (embedded) documents. + * For a non-nested search, use {@link #filter(Bson)} instead.
+ *Unlike some other MongoDB drivers, the Java driver does not automatically re-route a top-level + * {@link #filter(Bson)} to {@code parentFilter} based on the path: you must call + * {@link #parentFilter(Bson)} explicitly to specify a parent (root-level) filter for a nested search.
+ * + * @param parentFilter A filter applied to the parent documents of a nested {@code $vectorSearch}. + * One may use {@link Filters} to create this filter, though not all filters may be supported. + * See the MongoDB documentation for the list of supported filters. + * @return A new {@link VectorSearchOptions}. + * @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch + * @mongodb.server.release 8.3 + * @since 5.10 + */ + VectorSearchOptions parentFilter(Bson parentFilter); + + /** + * Creates a new {@link VectorSearchOptions} with the {@code nestedOptions} specified. + * + *Applies only when searching against arrays of embeddings within nested (embedded) documents; + * for example it controls how the scores of the individual matching embeddings within a document are + * aggregated (see {@link VectorSearchNestedOptions#scoreMode(VectorSearchScoreMode)}).
+ * + * @param nestedOptions The options for a nested (embedded) {@code $vectorSearch}. + * @return A new {@link VectorSearchOptions}. + * @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch + * @mongodb.server.release 8.3 + * @since 5.10 + */ + VectorSearchOptions nestedOptions(VectorSearchNestedOptions nestedOptions); + /** * Creates a new {@link VectorSearchOptions} that instructs to return only stored source fields. * diff --git a/driver-core/src/main/com/mongodb/client/model/search/VectorSearchScoreMode.java b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchScoreMode.java new file mode 100644 index 00000000000..917573024e2 --- /dev/null +++ b/driver-core/src/main/com/mongodb/client/model/search/VectorSearchScoreMode.java @@ -0,0 +1,54 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +package com.mongodb.client.model.search; + +/** + * The score aggregation mode for a {@code $vectorSearch} against arrays of embeddings in nested (embedded) documents. + * + *If {@code scoreMode} is not specified, the server default is {@link #MAX} ({@code "max"}).
+ * + * @see VectorSearchNestedOptions#scoreMode(VectorSearchScoreMode) + * @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch + * @mongodb.server.release 8.3 + * @since 5.10 + */ +public enum VectorSearchScoreMode { + /** + * Use the average of the scores of the matching embeddings within a document. + */ + AVG("avg"), + + /** + * Use the maximum of the scores of the matching embeddings within a document. + */ + MAX("max"); + + private final String value; + + VectorSearchScoreMode(final String value) { + this.value = value; + } + + /** + * Returns the value used by the server for this score mode. + * + * @return the server value ({@code "avg"} or {@code "max"}). + * @since 5.10 + */ + public String getValue() { + return value; + } +} diff --git a/driver-core/src/test/unit/com/mongodb/client/model/search/VectorSearchNestedOptionsTest.java b/driver-core/src/test/unit/com/mongodb/client/model/search/VectorSearchNestedOptionsTest.java new file mode 100644 index 00000000000..6b1918ff014 --- /dev/null +++ b/driver-core/src/test/unit/com/mongodb/client/model/search/VectorSearchNestedOptionsTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +package com.mongodb.client.model.search; + +import org.bson.BsonDocument; +import org.bson.BsonString; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +final class VectorSearchNestedOptionsTest { + @Test + void empty() { + assertEquals( + new BsonDocument(), + VectorSearchNestedOptions.vectorSearchNestedOptions().toBsonDocument() + ); + } + + @Test + void scoreMode() { + assertEquals( + new BsonDocument("scoreMode", new BsonString("avg")), + VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.AVG) + .toBsonDocument() + ); + } + + @Test + void scoreModeMaximum() { + assertEquals( + new BsonDocument("scoreMode", new BsonString("max")), + VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.MAX) + .toBsonDocument() + ); + } + + @Test + void scoreModeLastWriteWins() { + assertEquals( + new BsonDocument("scoreMode", new BsonString("avg")), + VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.MAX) + .scoreMode(VectorSearchScoreMode.AVG) + .toBsonDocument() + ); + } + + @Test + void optionEquivalentToScoreMode() { + assertEquals( + VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.AVG) + .toBsonDocument(), + VectorSearchNestedOptions.vectorSearchNestedOptions() + .option("scoreMode", "avg") + .toBsonDocument() + ); + } + + @Test + void scoreModeNull() { + assertThrows(IllegalArgumentException.class, () -> + VectorSearchNestedOptions.vectorSearchNestedOptions().scoreMode(null)); + } + + @Test + void optionNullName() { + assertThrows(IllegalArgumentException.class, () -> + VectorSearchNestedOptions.vectorSearchNestedOptions().option(null, "value")); + } + + @Test + void optionNullValue() { + assertThrows(IllegalArgumentException.class, () -> + VectorSearchNestedOptions.vectorSearchNestedOptions().option("scoreMode", null)); + } + + @Test + void vectorSearchNestedOptionsIsUnmodifiable() { + String expected = VectorSearchNestedOptions.vectorSearchNestedOptions().toBsonDocument().toJson(); + VectorSearchNestedOptions.vectorSearchNestedOptions().option("name", "value"); + assertEquals(expected, VectorSearchNestedOptions.vectorSearchNestedOptions().toBsonDocument().toJson()); + } + + @Test + void vectorSearchNestedOptionsIsImmutable() { + String expected = VectorSearchNestedOptions.vectorSearchNestedOptions().toBsonDocument().toJson(); + VectorSearchNestedOptions.vectorSearchNestedOptions().toBsonDocument().append("name", new BsonString("value")); + assertEquals(expected, VectorSearchNestedOptions.vectorSearchNestedOptions().toBsonDocument().toJson()); + } +} diff --git a/driver-core/src/test/unit/com/mongodb/client/model/search/BinaryVectorSearchOptionsTest.java b/driver-core/src/test/unit/com/mongodb/client/model/search/VectorSearchOptionsTest.java similarity index 61% rename from driver-core/src/test/unit/com/mongodb/client/model/search/BinaryVectorSearchOptionsTest.java rename to driver-core/src/test/unit/com/mongodb/client/model/search/VectorSearchOptionsTest.java index 952974b8edd..5b59cb74170 100644 --- a/driver-core/src/test/unit/com/mongodb/client/model/search/BinaryVectorSearchOptionsTest.java +++ b/driver-core/src/test/unit/com/mongodb/client/model/search/VectorSearchOptionsTest.java @@ -23,8 +23,9 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; -final class BinaryVectorSearchOptionsTest { +final class VectorSearchOptionsTest { @Test void approximateVectorSearchOptions() { assertEquals( @@ -78,6 +79,48 @@ void filterExact() { ); } + @Test + void parentFilter() { + assertEquals( + new BsonDocument() + .append("parentFilter", Filters.gt("year", 1900).toBsonDocument()) + .append("numCandidates", new BsonInt64(1)), + VectorSearchOptions.approximateVectorSearchOptions(1) + .parentFilter(Filters.gt("year", 1900)) + .toBsonDocument() + ); + } + + @Test + void nestedOptions() { + assertEquals( + new BsonDocument() + .append("nestedOptions", new BsonDocument("scoreMode", new BsonString("avg"))) + .append("numCandidates", new BsonInt64(1)), + VectorSearchOptions.approximateVectorSearchOptions(1) + .nestedOptions(VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.AVG)) + .toBsonDocument() + ); + } + + @Test + void filterParentFilterAndNestedOptions() { + assertEquals( + new BsonDocument() + .append("filter", Filters.lt("fieldName", 1).toBsonDocument()) + .append("parentFilter", Filters.gt("year", 1900).toBsonDocument()) + .append("nestedOptions", new BsonDocument("scoreMode", new BsonString("avg"))) + .append("numCandidates", new BsonInt64(1)), + VectorSearchOptions.approximateVectorSearchOptions(1) + .filter(Filters.lt("fieldName", 1)) + .parentFilter(Filters.gt("year", 1900)) + .nestedOptions(VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.AVG)) + .toBsonDocument() + ); + } + @Test void optionsApproximate() { assertEquals( @@ -134,6 +177,46 @@ void returnStoredSourceExact() { ); } + @Test + void parentFilterLastWriteWins() { + assertEquals( + new BsonDocument() + .append("parentFilter", Filters.gt("year", 2000).toBsonDocument()) + .append("numCandidates", new BsonInt64(1)), + VectorSearchOptions.approximateVectorSearchOptions(1) + .parentFilter(Filters.gt("year", 1900)) + .parentFilter(Filters.gt("year", 2000)) + .toBsonDocument() + ); + } + + @Test + void nestedOptionsLastWriteWins() { + assertEquals( + new BsonDocument() + .append("nestedOptions", new BsonDocument("scoreMode", new BsonString("max"))) + .append("numCandidates", new BsonInt64(1)), + VectorSearchOptions.approximateVectorSearchOptions(1) + .nestedOptions(VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.AVG)) + .nestedOptions(VectorSearchNestedOptions.vectorSearchNestedOptions() + .scoreMode(VectorSearchScoreMode.MAX)) + .toBsonDocument() + ); + } + + @Test + void parentFilterNull() { + assertThrows(IllegalArgumentException.class, () -> + VectorSearchOptions.approximateVectorSearchOptions(1).parentFilter(null)); + } + + @Test + void nestedOptionsNull() { + assertThrows(IllegalArgumentException.class, () -> + VectorSearchOptions.approximateVectorSearchOptions(1).nestedOptions(null)); + } + @Test void approximateVectorSearchOptionsIsUnmodifiable() { String expected = VectorSearchOptions.approximateVectorSearchOptions(1).toBsonDocument().toJson(); diff --git a/driver-scala/AGENTS.md b/driver-scala/AGENTS.md index 3e22456ea26..0b339e42ab9 100644 --- a/driver-scala/AGENTS.md +++ b/driver-scala/AGENTS.md @@ -23,3 +23,27 @@ Scala async driver providing Observable-based API wrapping `driver-reactive-stre ``` See [README.md](./README.md) for directory layout details. + +## Notes + +- **Mirror new public Java types in Scala.** Adding a public type or enum under a + wrapped package (`com.mongodb`, `com.mongodb.client.model` and its subpackages, + `com.mongodb.connection`, `com.mongodb.client.result`, …) requires a matching wrapper + in the corresponding `org.mongodb.scala.*` package — this is enforced by + `ApiAliasAndCompanionSpec` (the build fails if a mirror is missing): + - Add a `type` alias in the package's `package.scala`, copying the Java class's + stability annotations (`@Sealed`, `@Beta(Reason.…)`). + - **Keep `@Beta` annotations in sync with their Java counterpart.** The Scala alias + (and any companion `object`) must carry `@Beta` if and only if the Java class does, + with the same `Reason` value(s). When a Java type is promoted to stable (its + `@Beta` removed) or its `Reason` changes, update the Scala side to match — a + stable Java class (no `@Beta`) must not carry a stale `@Beta` on its Scala alias. + - **Every wrapped public enum needs a companion `object`** re-exposing each constant + as a `val` (see `ReturnDocument.scala`, `CollationStrength.scala`); a `type` alias + alone does not bring the enum constants into term scope, so `MyEnum.CONSTANT` would + not resolve for Scala users. + - For a type with factory methods, add a companion `object`. Follow the surrounding + package's convention: `model` uses an inline `object X { def apply(): X = new … }` + in `package.scala` for constructor-based options, whereas `model/search` uses a + dedicated-file `object` exposing each factory under its Java name (e.g. + `vectorSearchNestedOptions()`), never `apply()`. diff --git a/driver-scala/src/main/scala/org/mongodb/scala/model/search/VectorSearchNestedOptions.scala b/driver-scala/src/main/scala/org/mongodb/scala/model/search/VectorSearchNestedOptions.scala new file mode 100644 index 00000000000..178818a8910 --- /dev/null +++ b/driver-scala/src/main/scala/org/mongodb/scala/model/search/VectorSearchNestedOptions.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ +package org.mongodb.scala.model.search + +import com.mongodb.client.model.search.{ VectorSearchNestedOptions => JVectorSearchNestedOptions } + +/** + * Represents the optional `\$vectorSearch` `nestedOptions` sub-document, + * used when searching against arrays of embeddings within nested (embedded) documents. + * + * @see [[https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/ \$vectorSearch]] + * @since 5.10 + */ +object VectorSearchNestedOptions { + + /** + * Returns `VectorSearchNestedOptions` that represents server defaults. + * + * @return `VectorSearchNestedOptions` that represents server defaults. + */ + def vectorSearchNestedOptions(): VectorSearchNestedOptions = JVectorSearchNestedOptions.vectorSearchNestedOptions() +} diff --git a/driver-scala/src/main/scala/org/mongodb/scala/model/search/VectorSearchScoreMode.scala b/driver-scala/src/main/scala/org/mongodb/scala/model/search/VectorSearchScoreMode.scala new file mode 100644 index 00000000000..7731c973a88 --- /dev/null +++ b/driver-scala/src/main/scala/org/mongodb/scala/model/search/VectorSearchScoreMode.scala @@ -0,0 +1,38 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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. + */ + +package org.mongodb.scala.model.search + +import com.mongodb.client.model.search.{ VectorSearchScoreMode => JVectorSearchScoreMode } + +/** + * The score aggregation mode for a `\$vectorSearch` against arrays of embeddings in nested (embedded) documents. + * + * @see [[https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/ \$vectorSearch]] + * @since 5.10 + */ +object VectorSearchScoreMode { + + /** + * Use the average of the scores of the matching embeddings within a document. + */ + val AVG: JVectorSearchScoreMode = JVectorSearchScoreMode.AVG + + /** + * Use the maximum of the scores of the matching embeddings within a document. + */ + val MAX: JVectorSearchScoreMode = JVectorSearchScoreMode.MAX +} diff --git a/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala b/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala index 01ddaffb29f..2c919c6f9b1 100644 --- a/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala +++ b/driver-scala/src/main/scala/org/mongodb/scala/model/search/package.scala @@ -310,7 +310,6 @@ package object search { * @since 4.11 */ @Sealed - @Beta(Array(Reason.SERVER)) type VectorSearchOptions = com.mongodb.client.model.search.VectorSearchOptions /** @@ -323,7 +322,6 @@ package object search { * @since 5.2 */ @Sealed - @Beta(Array(Reason.SERVER)) type ApproximateVectorSearchOptions = com.mongodb.client.model.search.ApproximateVectorSearchOptions /** @@ -337,9 +335,26 @@ package object search { * @since 5.2 */ @Sealed - @Beta(Array(Reason.SERVER)) type ExactVectorSearchOptions = com.mongodb.client.model.search.ExactVectorSearchOptions + /** + * Represents the optional `nestedOptions` sub-document of the `\$vectorSearch` pipeline stage, + * used when searching against arrays of embeddings within nested (embedded) documents. + * + * @see [[https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/ \$vectorSearch]] + * @since 5.10 + */ + @Sealed + type VectorSearchNestedOptions = com.mongodb.client.model.search.VectorSearchNestedOptions + + /** + * The score aggregation mode for a `\$vectorSearch` against arrays of embeddings in nested (embedded) documents. + * + * @see [[https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/ \$vectorSearch]] + * @since 5.10 + */ + type VectorSearchScoreMode = com.mongodb.client.model.search.VectorSearchScoreMode + /** * Highlighting options. * You may use the `\$meta: "searchHighlights"` expression, e.g., via [[Projections.metaSearchHighlights]], diff --git a/driver-scala/src/test/scala-2/org/mongodb/scala/ApiAliasAndCompanionSpec.scala b/driver-scala/src/test/scala-2/org/mongodb/scala/ApiAliasAndCompanionSpec.scala index 99fb5a5e783..1a5b62094c6 100644 --- a/driver-scala/src/test/scala-2/org/mongodb/scala/ApiAliasAndCompanionSpec.scala +++ b/driver-scala/src/test/scala-2/org/mongodb/scala/ApiAliasAndCompanionSpec.scala @@ -308,13 +308,14 @@ class ApiAliasAndCompanionSpec extends BaseSpec { it should "mirror all com.mongodb.client.model.search in org.mongdb.scala.model.search" in { val packageName = "com.mongodb.client.model.search" - val wrapped = new Reflections(packageName, new SubTypesScanner(false)) - .getSubTypesOf(classOf[Object]) - .asScala - .filter(_.getPackage.getName == packageName) - .filter(classFilter) - .map(_.getSimpleName) - .toSet + val reflections = new Reflections(packageName, new SubTypesScanner(false)) + val wrapped = + (reflections.getSubTypesOf(classOf[Object]).asScala ++ + reflections.getSubTypesOf(classOf[Enum[_]]).asScala) + .filter(_.getPackage.getName == packageName) + .filter(classFilter) + .map(_.getSimpleName) + .toSet val scalaPackageName = "org.mongodb.scala.model.search" val localPackage = currentMirror.staticPackage(scalaPackageName).info.decls.map(_.name.toString).toSet val localObjects = new Reflections(scalaPackageName, new SubTypesScanner(false))