diff --git a/driver-core/src/main/com/mongodb/client/model/VectorSearchIndexDefinition.java b/driver-core/src/main/com/mongodb/client/model/VectorSearchIndexDefinition.java
index 25e87ce113..12b90751e0 100644
--- a/driver-core/src/main/com/mongodb/client/model/VectorSearchIndexDefinition.java
+++ b/driver-core/src/main/com/mongodb/client/model/VectorSearchIndexDefinition.java
@@ -16,6 +16,7 @@
package com.mongodb.client.model;
+import com.mongodb.lang.Nullable;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.codecs.configuration.CodecRegistry;
@@ -38,10 +39,32 @@
*/
public final class VectorSearchIndexDefinition implements SearchIndexDefinition {
private final List extends Bson> fields;
+ @Nullable
+ private final Bson storedSource;
VectorSearchIndexDefinition(final List extends Bson> fields) {
+ this(fields, null);
+ }
+
+ VectorSearchIndexDefinition(final List extends Bson> fields, @Nullable final Bson storedSource) {
doesNotContainNull("fields", notNull("fields", fields));
this.fields = new ArrayList<>(fields);
+ this.storedSource = storedSource;
+ }
+
+ /**
+ * Creates a new {@link VectorSearchIndexDefinition} with the specified stored source configuration.
+ *
+ *
The stored source configuration controls which fields are stored in the index
+ * and can be returned without reading the full document from the collection.
+ *
+ * @param storedSource a document specifying the stored source configuration,
+ * e.g., {@code {"include": ["field1", "field2"]}} or {@code {"exclude": ["field3"]}}
+ * @return a new {@link VectorSearchIndexDefinition} with the stored source configuration
+ * @since 5.8
+ */
+ public VectorSearchIndexDefinition storedSource(final Bson storedSource) {
+ return new VectorSearchIndexDefinition(this.fields, notNull("storedSource", storedSource));
}
@Override
@@ -50,13 +73,18 @@ public BsonDocument toBsonDocument(final Class documentCl
for (Bson field : fields) {
fieldArray.add(field.toBsonDocument(documentClass, codecRegistry));
}
- return new BsonDocument("fields", fieldArray);
+ BsonDocument document = new BsonDocument("fields", fieldArray);
+ if (storedSource != null) {
+ document.append("storedSource", storedSource.toBsonDocument(documentClass, codecRegistry));
+ }
+ return document;
}
@Override
public String toString() {
return "VectorSearchIndexDefinition{"
+ "fields=" + fields
+ + ", storedSource=" + storedSource
+ '}';
}
}
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 3e28189082..39a043ca82 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
@@ -17,6 +17,7 @@
import com.mongodb.annotations.Immutable;
import com.mongodb.internal.client.model.AbstractConstructibleBson;
+import org.bson.BsonBoolean;
import org.bson.BsonDocument;
import org.bson.Document;
import org.bson.conversions.Bson;
@@ -45,7 +46,12 @@ protected VectorSearchConstructibleBson newSelf(final Bson base, final Document
@Override
public VectorSearchOptions filter(final Bson filter) {
- return newAppended("filter", notNull("name", filter));
+ return newAppended("filter", notNull("filter", filter));
+ }
+
+ @Override
+ public VectorSearchOptions returnStoredSource(final boolean returnStoredSource) {
+ return newAppended("returnStoredSource", new BsonBoolean(returnStoredSource));
}
@Override
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 073c05b237..d3bcf3aea4 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
@@ -41,6 +41,16 @@ public interface VectorSearchOptions extends Bson {
*/
VectorSearchOptions filter(Bson filter);
+ /**
+ * Creates a new {@link VectorSearchOptions} that instructs to return only stored source fields.
+ *
+ * @param returnStoredSource The option to return only stored source fields.
+ * @return A new {@link VectorSearchOptions}.
+ * @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
+ * @since 5.8
+ */
+ VectorSearchOptions returnStoredSource(boolean returnStoredSource);
+
/**
* Creates a new {@link VectorSearchOptions} with the specified option in situations when there is no builder method
* that better satisfies your needs.
diff --git a/driver-core/src/test/unit/com/mongodb/client/model/SearchIndexDefinitionTest.java b/driver-core/src/test/unit/com/mongodb/client/model/SearchIndexDefinitionTest.java
index 87633f842f..31c34d82aa 100644
--- a/driver-core/src/test/unit/com/mongodb/client/model/SearchIndexDefinitionTest.java
+++ b/driver-core/src/test/unit/com/mongodb/client/model/SearchIndexDefinitionTest.java
@@ -141,4 +141,36 @@ void vectorSearchRejectsEmptyVarargs() {
void vectorSearchRejectsEmptyList() {
assertThrows(IllegalArgumentException.class, () -> SearchIndexDefinition.vectorSearch(emptyList()));
}
+
+ @Test
+ void vectorSearchWithStoredSource() {
+ VectorSearchIndexDefinition definition = SearchIndexDefinition.vectorSearch(
+ vectorField("embedding")
+ .numDimensions(1536)
+ .similarity("cosine")
+ ).storedSource(new Document("include", asList("plot", "title")));
+
+ assertEquals(
+ new BsonDocument("fields", new BsonArray(asList(
+ new BsonDocument("type", new BsonString("vector"))
+ .append("path", new BsonString("embedding"))
+ .append("numDimensions", new BsonInt32(1536))
+ .append("similarity", new BsonString("cosine"))
+ ))).append("storedSource", new BsonDocument("include", new BsonArray(asList(
+ new BsonString("plot"),
+ new BsonString("title")
+ )))),
+ definition.toBsonDocument()
+ );
+ }
+
+ @Test
+ void vectorSearchStoredSourceRejectsNull() {
+ VectorSearchIndexDefinition definition = SearchIndexDefinition.vectorSearch(
+ vectorField("embedding")
+ .numDimensions(1536)
+ .similarity("cosine")
+ );
+ assertThrows(IllegalArgumentException.class, () -> definition.storedSource(null));
+ }
}
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/BinaryVectorSearchOptionsTest.java
index 1fde037dbe..952974b8ed 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/BinaryVectorSearchOptionsTest.java
@@ -110,6 +110,30 @@ void optionsExact() {
);
}
+ @Test
+ void returnStoredSourceApproximate() {
+ assertEquals(
+ new BsonDocument()
+ .append("returnStoredSource", new BsonBoolean(true))
+ .append("numCandidates", new BsonInt64(1)),
+ VectorSearchOptions.approximateVectorSearchOptions(1)
+ .returnStoredSource(true)
+ .toBsonDocument()
+ );
+ }
+
+ @Test
+ void returnStoredSourceExact() {
+ assertEquals(
+ new BsonDocument()
+ .append("returnStoredSource", new BsonBoolean(true))
+ .append("exact", new BsonBoolean(true)),
+ VectorSearchOptions.exactVectorSearchOptions()
+ .returnStoredSource(true)
+ .toBsonDocument()
+ );
+ }
+
@Test
void approximateVectorSearchOptionsIsUnmodifiable() {
String expected = VectorSearchOptions.approximateVectorSearchOptions(1).toBsonDocument().toJson();
diff --git a/driver-scala/src/test/scala/org/mongodb/scala/model/SearchIndexDefinitionSpec.scala b/driver-scala/src/test/scala/org/mongodb/scala/model/SearchIndexDefinitionSpec.scala
index fd36ef5246..efbe29917f 100644
--- a/driver-scala/src/test/scala/org/mongodb/scala/model/SearchIndexDefinitionSpec.scala
+++ b/driver-scala/src/test/scala/org/mongodb/scala/model/SearchIndexDefinitionSpec.scala
@@ -77,6 +77,20 @@ class SearchIndexDefinitionSpec extends BaseSpec {
)
}
+ it should "create a vectorSearch definition with storedSource" in {
+ toBson(
+ vectorSearch(
+ vectorField("embedding").numDimensions(1536).similarity("cosine")
+ ).storedSource(Document("include" -> List("plot", "title")))
+ ) should equal(
+ Document(
+ """{"fields": [
+ |{"type": "vector", "path": "embedding", "numDimensions": 1536, "similarity": "cosine"}
+ |], "storedSource": {"include": ["plot", "title"]}}""".stripMargin.replaceAll("\n", " ")
+ )
+ )
+ }
+
it should "create a SearchIndexModel with VectorSearchIndexDefinition" in {
val definition = vectorSearch(
vectorField("embedding").numDimensions(1536).similarity("cosine")