Skip to content

Commit 634fd09

Browse files
vbabaninstIncMale
andauthored
Add exact vector search option. (#1473)
JAVA-5557 --------- Co-authored-by: Valentin Kovalenko <[email protected]>
1 parent 5059158 commit 634fd09

File tree

14 files changed

+256
-128
lines changed

14 files changed

+256
-128
lines changed

driver-core/src/main/com/mongodb/client/model/Aggregates.java

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import static com.mongodb.client.model.GeoNearOptions.geoNearOptions;
5353
import static com.mongodb.client.model.densify.DensifyOptions.densifyOptions;
5454
import static com.mongodb.client.model.search.SearchOptions.searchOptions;
55-
import static com.mongodb.client.model.search.VectorSearchOptions.vectorSearchOptions;
5655
import static com.mongodb.internal.Iterables.concat;
5756
import static com.mongodb.internal.client.model.Util.sizeAtLeast;
5857
import static java.util.Arrays.asList;
@@ -947,50 +946,20 @@ public static Bson searchMeta(final SearchCollector collector, final SearchOptio
947946
* @param queryVector The query vector. The number of dimensions must match that of the {@code index}.
948947
* @param path The field to be searched.
949948
* @param index The name of the index to use.
950-
* @param numCandidates The number of candidates.
951-
* @param limit The limit on the number of documents produced by the pipeline stage.
952-
* @return The {@code $vectorSearch} pipeline stage.
953-
*
954-
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
955-
* @mongodb.atlas.manual atlas-search/scoring/ Scoring
956-
* @mongodb.server.release 6.0.10
957-
* @since 4.11
958-
*/
959-
@Beta(Reason.SERVER)
960-
public static Bson vectorSearch(
961-
final FieldSearchPath path,
962-
final Iterable<Double> queryVector,
963-
final String index,
964-
final long numCandidates,
965-
final long limit) {
966-
return vectorSearch(notNull("path", path), notNull("queryVector", queryVector), notNull("index", index), numCandidates, limit,
967-
vectorSearchOptions());
968-
}
969-
970-
/**
971-
* Creates a {@code $vectorSearch} pipeline stage supported by MongoDB Atlas.
972-
* You may use the {@code $meta: "vectorSearchScore"} expression, e.g., via {@link Projections#metaVectorSearchScore(String)},
973-
* to extract the relevance score assigned to each found document.
974-
*
975-
* @param queryVector The query vector. The number of dimensions must match that of the {@code index}.
976-
* @param path The field to be searched.
977-
* @param index The name of the index to use.
978-
* @param numCandidates The number of candidates.
979949
* @param limit The limit on the number of documents produced by the pipeline stage.
980950
* @param options Optional {@code $vectorSearch} pipeline stage fields.
981951
* @return The {@code $vectorSearch} pipeline stage.
982952
*
983953
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
984954
* @mongodb.atlas.manual atlas-search/scoring/ Scoring
985-
* @mongodb.server.release 6.0.10
955+
* @mongodb.server.release 6.0.11
986956
* @since 4.11
987957
*/
988958
@Beta(Reason.SERVER)
989959
public static Bson vectorSearch(
990960
final FieldSearchPath path,
991961
final Iterable<Double> queryVector,
992962
final String index,
993-
final long numCandidates,
994963
final long limit,
995964
final VectorSearchOptions options) {
996965
notNull("path", path);
@@ -1003,7 +972,6 @@ public <TDocument> BsonDocument toBsonDocument(final Class<TDocument> documentCl
1003972
Document specificationDoc = new Document("path", path.toValue())
1004973
.append("queryVector", queryVector)
1005974
.append("index", index)
1006-
.append("numCandidates", numCandidates)
1007975
.append("limit", limit);
1008976
specificationDoc.putAll(options.toBsonDocument(documentClass, codecRegistry));
1009977
return new Document("$vectorSearch", specificationDoc).toBsonDocument(documentClass, codecRegistry);
@@ -1015,7 +983,6 @@ public String toString() {
1015983
+ ", path=" + path
1016984
+ ", queryVector=" + queryVector
1017985
+ ", index=" + index
1018-
+ ", numCandidates=" + numCandidates
1019986
+ ", limit=" + limit
1020987
+ ", options=" + options
1021988
+ '}';

driver-core/src/main/com/mongodb/client/model/Projections.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public static Bson metaSearchScore(final String fieldName) {
215215

216216
/**
217217
* Creates a projection to the given field name of the vectorSearchScore,
218-
* for use with {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, long, VectorSearchOptions)}.
218+
* for use with {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)} .
219219
* Calling this method is equivalent to calling {@link #meta(String, String)} with {@code "vectorSearchScore"} as the second argument.
220220
*
221221
* @param fieldName the field name
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.client.model.search;
18+
19+
import com.mongodb.annotations.Beta;
20+
import com.mongodb.annotations.Reason;
21+
import com.mongodb.annotations.Sealed;
22+
import com.mongodb.client.model.Aggregates;
23+
24+
/**
25+
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
26+
* <p>
27+
* Configures approximate vector search for Atlas Vector Search to enable searches that may not return the exact closest vectors.
28+
*
29+
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)
30+
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
31+
* @mongodb.server.release 6.0.11, 7.0.2
32+
* @since 5.2
33+
*/
34+
@Sealed
35+
@Beta(Reason.SERVER)
36+
public interface ApproximateVectorSearchOptions extends VectorSearchOptions {
37+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.client.model.search;
18+
19+
import com.mongodb.annotations.Beta;
20+
import com.mongodb.annotations.Reason;
21+
import com.mongodb.annotations.Sealed;
22+
import com.mongodb.client.model.Aggregates;
23+
24+
/**
25+
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
26+
* <p>
27+
* Configures exact vector search for Atlas Vector Search to enable precise matching, ensuring that
28+
* results are the closest vectors to a given query vector.
29+
*
30+
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)
31+
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
32+
* @mongodb.server.release 6.0.16, 7.0.10, 7.3.2
33+
* @since 5.2
34+
*/
35+
@Sealed
36+
@Beta(Reason.SERVER)
37+
public interface ExactVectorSearchOptions extends VectorSearchOptions {
38+
}

driver-core/src/main/com/mongodb/client/model/search/VectorSearchConstructibleBson.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323

2424
import static com.mongodb.assertions.Assertions.notNull;
2525

26-
final class VectorSearchConstructibleBson extends AbstractConstructibleBson<VectorSearchConstructibleBson> implements VectorSearchOptions {
26+
final class VectorSearchConstructibleBson extends AbstractConstructibleBson<VectorSearchConstructibleBson>
27+
implements ApproximateVectorSearchOptions, ExactVectorSearchOptions {
2728
/**
2829
* An {@linkplain Immutable immutable} {@link BsonDocument#isEmpty() empty} instance.
2930
*/

driver-core/src/main/com/mongodb/client/model/search/VectorSearchOptions.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
/**
2626
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
2727
*
28-
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, long, VectorSearchOptions)
28+
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)
2929
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
30-
* @mongodb.server.release 6.0.10
30+
* @mongodb.server.release 6.0.11
3131
* @since 4.11
3232
*/
3333
@Sealed
@@ -37,7 +37,7 @@ public interface VectorSearchOptions extends Bson {
3737
* Creates a new {@link VectorSearchOptions} with the filter specified.
3838
*
3939
* @param filter A filter that is applied before applying the
40-
* {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, long, VectorSearchOptions) queryVector}.
40+
* {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions) queryVector}
4141
* One may use {@link Filters} to create this filter, though not all filters may be supported.
4242
* See the MongoDB documentation for the list of supported filters.
4343
* @return A new {@link VectorSearchOptions}.
@@ -66,11 +66,24 @@ public interface VectorSearchOptions extends Bson {
6666
VectorSearchOptions option(String name, Object value);
6767

6868
/**
69-
* Returns {@link VectorSearchOptions} that represents server defaults.
69+
* Returns {@link ApproximateVectorSearchOptions} that represents server defaults.
7070
*
71-
* @return {@link VectorSearchOptions} that represents server defaults.
71+
* @param numCandidates The number of candidates.
72+
* @return {@link ApproximateVectorSearchOptions} that represents server defaults.
73+
* @since 5.2
7274
*/
73-
static VectorSearchOptions vectorSearchOptions() {
74-
return VectorSearchConstructibleBson.EMPTY_IMMUTABLE;
75+
static ApproximateVectorSearchOptions approximateVectorSearchOptions(long numCandidates) {
76+
return (ApproximateVectorSearchOptions) VectorSearchConstructibleBson.EMPTY_IMMUTABLE.option("numCandidates", numCandidates);
77+
}
78+
79+
/**
80+
* Returns {@link ExactVectorSearchOptions} that represents server defaults with the {@code exact} option set to true.
81+
*
82+
* @return {@link ExactVectorSearchOptions} that represents server defaults.
83+
* @since 5.2
84+
*/
85+
static ExactVectorSearchOptions exactVectorSearchOptions() {
86+
return (ExactVectorSearchOptions) VectorSearchConstructibleBson.EMPTY_IMMUTABLE
87+
.option("exact", true);
7588
}
7689
}

driver-core/src/main/com/mongodb/client/model/search/package-info.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
*
2626
* @see com.mongodb.client.model.Aggregates#search(SearchOperator, SearchOptions)
2727
* @see com.mongodb.client.model.Aggregates#search(SearchCollector, SearchOptions)
28-
* @see com.mongodb.client.model.Aggregates#vectorSearch(FieldSearchPath, java.lang.Iterable, java.lang.String, long, long, VectorSearchOptions)
28+
* @see com.mongodb.client.model.Aggregates#vectorSearch(com.mongodb.client.model.search.FieldSearchPath, java.lang.Iterable, java.lang.String,
29+
* long, com.mongodb.client.model.search.VectorSearchOptions)
2930
* @mongodb.atlas.manual atlas-search/ Atlas Search
3031
* @mongodb.atlas.manual atlas-search/query-syntax/ Atlas Search aggregation pipeline stages
3132
* @since 4.7

driver-core/src/test/functional/com/mongodb/client/model/search/AggregatesSearchIntegrationTest.java

Lines changed: 29 additions & 13 deletions
Large diffs are not rendered by default.

driver-core/src/test/unit/com/mongodb/client/model/AggregatesSpecification.groovy

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ import static com.mongodb.client.model.search.SearchOperator.exists
9898
import static com.mongodb.client.model.search.SearchOptions.searchOptions
9999
import static com.mongodb.client.model.search.SearchPath.fieldPath
100100
import static com.mongodb.client.model.search.SearchPath.wildcardPath
101-
import static com.mongodb.client.model.search.VectorSearchOptions.vectorSearchOptions
101+
import static com.mongodb.client.model.search.VectorSearchOptions.approximateVectorSearchOptions
102+
import static com.mongodb.client.model.search.VectorSearchOptions.exactVectorSearchOptions
102103
import static java.util.Arrays.asList
103104
import static org.bson.BsonDocument.parse
104105

@@ -849,16 +850,15 @@ class AggregatesSpecification extends Specification {
849850
}''')
850851
}
851852

852-
def 'should render $vectorSearch'() {
853+
def 'should render approximate $vectorSearch'() {
853854
when:
854855
BsonDocument vectorSearchDoc = toBson(
855856
vectorSearch(
856857
fieldPath('fieldName').multi('ignored'),
857858
[1.0d, 2.0d],
858859
'indexName',
859-
2,
860860
1,
861-
vectorSearchOptions()
861+
approximateVectorSearchOptions(2)
862862
.filter(Filters.ne("fieldName", "fieldValue"))
863863

864864
)
@@ -877,15 +877,17 @@ class AggregatesSpecification extends Specification {
877877
}''')
878878
}
879879

880-
def 'should render $vectorSearch with no options'() {
880+
def 'should render exact $vectorSearch'() {
881881
when:
882882
BsonDocument vectorSearchDoc = toBson(
883883
vectorSearch(
884-
fieldPath('fieldName'),
884+
fieldPath('fieldName').multi('ignored'),
885885
[1.0d, 2.0d],
886886
'indexName',
887-
2,
888-
1
887+
1,
888+
exactVectorSearchOptions()
889+
.filter(Filters.ne("fieldName", "fieldValue"))
890+
889891
)
890892
)
891893

@@ -895,8 +897,9 @@ class AggregatesSpecification extends Specification {
895897
"path": "fieldName",
896898
"queryVector": [1.0, 2.0],
897899
"index": "indexName",
898-
"numCandidates": {"$numberLong": "2"},
899-
"limit": {"$numberLong": "1"}
900+
"exact": true,
901+
"limit": {"$numberLong": "1"},
902+
"filter": {"fieldName": {"$ne": "fieldValue"}}
900903
}
901904
}''')
902905
}

0 commit comments

Comments
 (0)