Skip to content

DOCSP-51350: Vector search queries #117

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 5 commits into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
125 changes: 124 additions & 1 deletion source/atlas-vector-search.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,127 @@

================================
Run an Atlas Vector Search Query
================================
================================

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: full text, text analyzer, meta, pipeline, scoring, Lucene, AI, artificial intelligence, code example, semantic, nearest
:description: Learn about how to use Atlas Vector Search in the {+driver-short+}.

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

Overview
--------

In this guide, you can learn how to use the {+driver-short+} to perform
:atlas:`Atlas Vector Search </atlas-vector-search/vector-search-overview/>`
queries. The ``Aggregates`` builders class provides the

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
the ``vectorSearch()`` helper method, which you can use to
``vectorSearch()`` helper method, which you can use to

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops thank you

the ``vectorSearch()`` helper method, which you can use to
create a :atlas:`$vectorSearch </atlas-vector-search/vector-search-stage/>`
pipeline stage.

.. important:: Feature Compatibility

To learn which versions of MongoDB Atlas support this feature, see
:atlas:`Limitations </atlas-vector-search/vector-search-stage/#limitations>`
in the MongoDB Atlas documentation.

Perform a Vector Search
-----------------------

Before you can perform Atlas Vector Search queries, you must create an Atlas Vector Search
index on your collection. To learn about how to programmatically create a
vector search index, see the :ref:`kotlin-sync-search-avs-indexes` guide.

Then, you can run an Atlas Vector Search query by using the
``vectorSearch()`` method in an aggregation pipeline. This
method accepts the following parameters:

- ``path``: The field to search
- ``queryVector``: The vector embedding that represents your search query
- ``indexName``: The name of the Atlas Vector Search index to use
- ``limit``: The maximum number of results to return
- ``options``: *(Optional)* A set of options that you can use to configure the
vector search query

Vector Search Example
~~~~~~~~~~~~~~~~~~~~~

The following example performs an Atlas Vector Search query on the ``plot_embedding``
vector field and prints the ``title`` value of the first five results:

.. io-code-block::

.. input:: /includes/vector-search.kt
:start-after: start-vs
:end-before: end-vs
:language: kotlin
:dedent:

.. output::
:visible: false

{"title": "Berserk: The Golden Age Arc I - The Egg of the King"}
{"title": "Rollerball"}
{"title": "After Life"}
{"title": "What Women Want"}
{"title": "Truth About Demons"}

.. tip:: Query Vector Type

The preceding example creates an instance of ``BinaryVector`` to
serve as the query vector, but you can also create a ``List`` of
``Double`` instances. However, we recommend that you use the
``BinaryVector`` type to improve storage efficiency.

The following example shows how to run the aggregation and print
the vector search meta-score from the result of the preceding
aggregation pipeline:

.. io-code-block::

.. input:: /includes/vector-search.kt
:start-after: start-vs-score
:end-before: end-vs-score
:language: kotlin
:dedent:

.. output::
:visible: false

Title: Berserk: The Golden Age Arc I - The Egg of the King, Score: 0.49899211525917053
Title: Rollerball, Score: 0.4976102113723755
Title: After Life, Score: 0.4965665936470032
Title: What Women Want, Score: 0.49622756242752075
Title: Truth About Demons, Score: 0.49614521861076355

.. tip:: Vector Search Tutorials

To view more tutorials that show how to run Atlas Vector Search queries,
see the :atlas:`Atlas Vector Search Tutorials </atlas-vector-search/tutorials>`
in the MongoDB Atlas documentation.

API Documentation
-----------------

To learn more about the methods and types mentioned in this
guide, see the following API documentation:

- `Aggregates.vectorSearch()
<{+core-api+}/client/model/Aggregates.html#vectorSearch(com.mongodb.client.model.search.FieldSearchPath,java.lang.Iterable,java.lang.String,long,com.mongodb.client.model.search.VectorSearchOptions)>`__

- `FieldSearchPath
<{+core-api+}/client/model/search/FieldSearchPath.html>`__

- `VectorSearchOptions
<{+core-api+}/client/model/search/VectorSearchOptions.html>`__

- `Projections.metaVectorSearchScore()
<{+core-api+}/client/model/Projections.html#metaVectorSearchScore(java.lang.String)>`__
85 changes: 85 additions & 0 deletions source/includes/vector-search.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package org.example

import com.mongodb.ConnectionString
import com.mongodb.kotlin.client.MongoClient
import com.mongodb.MongoClientSettings
import com.mongodb.client.model.Aggregates.project
import com.mongodb.client.model.Aggregates.vectorSearch
import com.mongodb.client.model.search.FieldSearchPath
import com.mongodb.client.model.Projections
import com.mongodb.client.model.search.SearchPath.fieldPath
import org.bson.BinaryVector
import org.bson.conversions.Bson
import com.mongodb.client.model.search.VectorSearchOptions.approximateVectorSearchOptions
import org.bson.Document

fun main() {
val uri = "<connection string>"

val settings = MongoClientSettings.builder()
.applyConnectionString(ConnectionString(uri))
.retryWrites(true)
.build()

val mongoClient = MongoClient.create(settings)
val database = mongoClient.getDatabase("sample_mflix")
val collection = database.getCollection<Document>("embedded_movies")

// start-vs
val vectorValues = FloatArray(1536) { i -> (i % 10).toFloat() * 0.1f }
val queryVector = BinaryVector.floatVector(vectorValues)
val indexName = "<vector search index>"

// Specifies the path of the field to search
val fieldSearchPath: FieldSearchPath = fieldPath("plot_embedding")

// Creates the vector search pipeline stage with numCandidates and limit

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given limit is used prior to numCandidates, it might be better to switch the order of them

val pipeline: List<Bson> = listOf(
vectorSearch(
fieldSearchPath,
queryVector,
indexName,
5L,
approximateVectorSearchOptions(150)
),
project(
Projections.fields(
Projections.excludeId(),
Projections.include("title")
)
)
)

val results = collection.aggregate(pipeline)

results.forEach { doc ->
println(doc.toJson())
}
// end-vs

// start-vs-score
val pipeline: List<Bson> = listOf(
vectorSearch(
fieldSearchPath,
queryVector,
indexName,
5L, // limit parameter
approximateVectorSearchOptions(150)
),
project(
Projections.fields(
Projections.excludeId(),
Projections.include("title"),
Projections.metaVectorSearchScore("score")
)
)
)

val results = collection.aggregate(pipeline)

results.forEach { doc ->
val score = doc.getDouble("vectorSearchScore")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need the above statement? I assume vectorSearchScore is a meta field name, but not the field name, so I guess doc.getDouble("vectorSearchScore") will return null invariably?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No not necessary, I meant to take that line out - fixed!

println("Title: ${doc.getString("title")}, Score: ${doc.getDouble("score")}")
}
// end-vs-score
}
Loading