Skip to content

Add exact vector search option. #1473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 1 addition & 34 deletions driver-core/src/main/com/mongodb/client/model/Aggregates.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import static com.mongodb.client.model.GeoNearOptions.geoNearOptions;
import static com.mongodb.client.model.densify.DensifyOptions.densifyOptions;
import static com.mongodb.client.model.search.SearchOptions.searchOptions;
import static com.mongodb.client.model.search.VectorSearchOptions.vectorSearchOptions;
import static com.mongodb.internal.Iterables.concat;
import static com.mongodb.internal.client.model.Util.sizeAtLeast;
import static java.util.Arrays.asList;
Expand Down Expand Up @@ -947,50 +946,20 @@ public static Bson searchMeta(final SearchCollector collector, final SearchOptio
* @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.
* @param numCandidates The number of candidates.
* @param limit The limit on the number of documents produced by the pipeline stage.
* @return The {@code $vectorSearch} pipeline stage.
*
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
* @mongodb.atlas.manual atlas-search/scoring/ Scoring
* @mongodb.server.release 6.0.10
* @since 4.11
*/
@Beta(Reason.SERVER)
public static Bson vectorSearch(
final FieldSearchPath path,
final Iterable<Double> queryVector,
final String index,
final long numCandidates,
final long limit) {
return vectorSearch(notNull("path", path), notNull("queryVector", queryVector), notNull("index", index), numCandidates, limit,
vectorSearchOptions());
}

/**
* Creates a {@code $vectorSearch} pipeline stage supported by MongoDB Atlas.
* 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.
*
* @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.
* @param numCandidates The number of candidates.
* @param limit The limit on the number of documents produced by the pipeline stage.
* @param options Optional {@code $vectorSearch} pipeline stage fields.
* @return The {@code $vectorSearch} pipeline stage.
*
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
* @mongodb.atlas.manual atlas-search/scoring/ Scoring
* @mongodb.server.release 6.0.10
* @mongodb.server.release 6.0.11
* @since 4.11
*/
@Beta(Reason.SERVER)
public static Bson vectorSearch(
final FieldSearchPath path,
final Iterable<Double> queryVector,
final String index,
final long numCandidates,
final long limit,
final VectorSearchOptions options) {
notNull("path", path);
Expand All @@ -1003,7 +972,6 @@ public <TDocument> BsonDocument toBsonDocument(final Class<TDocument> documentCl
Document specificationDoc = new Document("path", path.toValue())
.append("queryVector", queryVector)
.append("index", index)
.append("numCandidates", numCandidates)
.append("limit", limit);
specificationDoc.putAll(options.toBsonDocument(documentClass, codecRegistry));
return new Document("$vectorSearch", specificationDoc).toBsonDocument(documentClass, codecRegistry);
Expand All @@ -1015,7 +983,6 @@ public String toString() {
+ ", path=" + path
+ ", queryVector=" + queryVector
+ ", index=" + index
+ ", numCandidates=" + numCandidates
+ ", limit=" + limit
+ ", options=" + options
+ '}';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public static Bson metaSearchScore(final String fieldName) {

/**
* Creates a projection to the given field name of the vectorSearchScore,
* for use with {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, long, VectorSearchOptions)}.
* for use with {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)} .
* Calling this method is equivalent to calling {@link #meta(String, String)} with {@code "vectorSearchScore"} as the second argument.
*
* @param fieldName the field name
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.Beta;
import com.mongodb.annotations.Reason;
import com.mongodb.annotations.Sealed;
import com.mongodb.client.model.Aggregates;

/**
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
* <p>
* Configures approximate vector search for Atlas Vector Search to enable searches that may not return the exact closest vectors.
*
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
* @mongodb.server.release 6.0.11, 7.0.2
* @since 5.2
*/
@Sealed
@Beta(Reason.SERVER)
public interface ApproximateVectorSearchOptions extends VectorSearchOptions {
}
Original file line number Diff line number Diff line change
@@ -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 com.mongodb.client.model.search;

import com.mongodb.annotations.Beta;
import com.mongodb.annotations.Reason;
import com.mongodb.annotations.Sealed;
import com.mongodb.client.model.Aggregates;

/**
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
* <p>
* Configures exact vector search for Atlas Vector Search to enable precise matching, ensuring that
* results are the closest vectors to a given query vector.
*
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
* @mongodb.server.release 6.0.16, 7.0.10, 7.3.2
* @since 5.2
*/
@Sealed
@Beta(Reason.SERVER)
public interface ExactVectorSearchOptions extends VectorSearchOptions {
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

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

final class VectorSearchConstructibleBson extends AbstractConstructibleBson<VectorSearchConstructibleBson> implements VectorSearchOptions {
final class VectorSearchConstructibleBson extends AbstractConstructibleBson<VectorSearchConstructibleBson>
implements ApproximateVectorSearchOptions, ExactVectorSearchOptions {
/**
* An {@linkplain Immutable immutable} {@link BsonDocument#isEmpty() empty} instance.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
/**
* Represents optional fields of the {@code $vectorSearch} pipeline stage of an aggregation pipeline.
*
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, long, VectorSearchOptions)
* @see Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions)
* @mongodb.atlas.manual atlas-vector-search/vector-search-stage/ $vectorSearch
* @mongodb.server.release 6.0.10
* @mongodb.server.release 6.0.11
* @since 4.11
*/
@Sealed
Expand All @@ -37,7 +37,7 @@ public interface VectorSearchOptions extends Bson {
* Creates a new {@link VectorSearchOptions} with the filter specified.
*
* @param filter A filter that is applied before applying the
* {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, long, VectorSearchOptions) queryVector}.
* {@link Aggregates#vectorSearch(FieldSearchPath, Iterable, String, long, VectorSearchOptions) queryVector}
* 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}.
Expand Down Expand Up @@ -66,11 +66,24 @@ public interface VectorSearchOptions extends Bson {
VectorSearchOptions option(String name, Object value);

/**
* Returns {@link VectorSearchOptions} that represents server defaults.
* Returns {@link ApproximateVectorSearchOptions} that represents server defaults.
*
* @return {@link VectorSearchOptions} that represents server defaults.
* @param numCandidates The number of candidates.
* @return {@link ApproximateVectorSearchOptions} that represents server defaults.
* @since 5.2
*/
static VectorSearchOptions vectorSearchOptions() {
return VectorSearchConstructibleBson.EMPTY_IMMUTABLE;
static ApproximateVectorSearchOptions approximateVectorSearchOptions(long numCandidates) {
return (ApproximateVectorSearchOptions) VectorSearchConstructibleBson.EMPTY_IMMUTABLE.option("numCandidates", numCandidates);
}

/**
* Returns {@link ExactVectorSearchOptions} that represents server defaults with the {@code exact} option set to true.
*
* @return {@link ExactVectorSearchOptions} that represents server defaults.
* @since 5.2
*/
static ExactVectorSearchOptions exactVectorSearchOptions() {
return (ExactVectorSearchOptions) VectorSearchConstructibleBson.EMPTY_IMMUTABLE
.option("exact", true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
*
* @see com.mongodb.client.model.Aggregates#search(SearchOperator, SearchOptions)
* @see com.mongodb.client.model.Aggregates#search(SearchCollector, SearchOptions)
* @see com.mongodb.client.model.Aggregates#vectorSearch(FieldSearchPath, java.lang.Iterable, java.lang.String, long, long, VectorSearchOptions)
* @see com.mongodb.client.model.Aggregates#vectorSearch(com.mongodb.client.model.search.FieldSearchPath, java.lang.Iterable, java.lang.String,
* long, com.mongodb.client.model.search.VectorSearchOptions)
* @mongodb.atlas.manual atlas-search/ Atlas Search
* @mongodb.atlas.manual atlas-search/query-syntax/ Atlas Search aggregation pipeline stages
* @since 4.7
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ import static com.mongodb.client.model.search.SearchOperator.exists
import static com.mongodb.client.model.search.SearchOptions.searchOptions
import static com.mongodb.client.model.search.SearchPath.fieldPath
import static com.mongodb.client.model.search.SearchPath.wildcardPath
import static com.mongodb.client.model.search.VectorSearchOptions.vectorSearchOptions
import static com.mongodb.client.model.search.VectorSearchOptions.approximateVectorSearchOptions
import static com.mongodb.client.model.search.VectorSearchOptions.exactVectorSearchOptions
import static java.util.Arrays.asList
import static org.bson.BsonDocument.parse

Expand Down Expand Up @@ -849,16 +850,15 @@ class AggregatesSpecification extends Specification {
}''')
}

def 'should render $vectorSearch'() {
def 'should render approximate $vectorSearch'() {
when:
BsonDocument vectorSearchDoc = toBson(
vectorSearch(
fieldPath('fieldName').multi('ignored'),
[1.0d, 2.0d],
'indexName',
2,
1,
vectorSearchOptions()
approximateVectorSearchOptions(2)
.filter(Filters.ne("fieldName", "fieldValue"))

)
Expand All @@ -877,15 +877,17 @@ class AggregatesSpecification extends Specification {
}''')
}

def 'should render $vectorSearch with no options'() {
def 'should render exact $vectorSearch'() {
when:
BsonDocument vectorSearchDoc = toBson(
vectorSearch(
fieldPath('fieldName'),
fieldPath('fieldName').multi('ignored'),
[1.0d, 2.0d],
'indexName',
2,
1
1,
exactVectorSearchOptions()
.filter(Filters.ne("fieldName", "fieldValue"))

)
)

Expand All @@ -895,8 +897,9 @@ class AggregatesSpecification extends Specification {
"path": "fieldName",
"queryVector": [1.0, 2.0],
"index": "indexName",
"numCandidates": {"$numberLong": "2"},
"limit": {"$numberLong": "1"}
"exact": true,
"limit": {"$numberLong": "1"},
"filter": {"fieldName": {"$ne": "fieldValue"}}
}
}''')
}
Expand Down
Loading