website/docs/guides/vector-search.mdx
import Tabs from '@theme/Tabs' import TabItem from '@theme/TabItem' import CodeBlock from '@theme/CodeBlock' import InsertData from '!!raw-loader!./vector-search/2-insert-data.request.js' import HNSWIndexRequest from '!!raw-loader!./vector-search/3-hnsw-index.request.js' import HNSWSearchRequest from '!!raw-loader!./vector-search/4-hnsw-search.request.js' import HNSWSearchResponse from '!!raw-loader!./vector-search/4-hnsw-search.response.js' import IVFIndexRequest from '!!raw-loader!./vector-search/6-ivf-index.request.js' import IVFSearchRequest from '!!raw-loader!./vector-search/7-ivf-search.request.js' import IVFSearchResponse from '!!raw-loader!./vector-search/7-ivf-search.response.js'
Vector search is a technique for retrieving contextual and semantically related items based on the similarity of their vector representations. It operates on numerical vectors, which represent data such as text, images, or audio. These vectors, known as vector embeddings, are typically generated using embedding models such as Word2Vec, GloVe, BERT, and GPT for text data, ResNet for image data, or Wav2Vec for audio data.
Vector search is widely used in various applications, especially to power generative AI workflows, such as conversational agents and chatbots. It is also used for building recommendation systems for personalized content and product suggestions, and to enable semantic search for context-aware document retrieval.
Every vector search application requires a method to calculate the similarity between two vectors. Similarity metrics such as Cosine similarity and Euclidean distance help calculate the distance between vectors and are essential for finding the nearest neighbors of a query from the same embedding model.
FerretDB supports the following vector index kinds:
Vector index can be created using the usual createIndexes command with the following syntax:
db.runCommand({
createIndexes: '<collectionName>',
indexes: [
{
name: '<indexName>',
key: {
'<path>': 'cosmosSearch'
},
cosmosSearchOptions: {
kind: '<kind>',
similarity: '<similarity>',
dimensions: '<dimensions>',
// HNSW only
m: '<m>',
efConstruction: '<efConstruction>',
// IVF only
numLists: '<numLists>'
}
}
]
})
A vector index definition can take the following parameters, depending on the kind of index:
| Field | Type | Description | Index kind |
|---|---|---|---|
<path> | string | The path to the field containing the vector embeddings. The field must be mapped to "cosmosSearch" to enable creation of a vector index. | All |
cosmosSearchOptions | document | It specifies the configuration parameters (kind, similarity, dimensions, etc.) for the vector index to suit your specific use case | All |
kind | string | The kind of index to create. Possible values: vector-hnsw, vector-ivf. | All |
similarity | string | The similarity metric to use for nearest neighbor search. Option could be COS for cosine similarity, L2 for Euclidean distance, or IP for inner product. | All |
dimensions | integer | The number of dimensions in the vector. Note that all vectors in the collection must have the same dimensionality. Must range from 2-16000 | All |
m | integer | The maximum number of connections per layer. Typically range from 2 to 100 (default: 16). | HNSW |
efConstruction | integer | The number of neighbors or dynamic candidate list to search during graph construction. Typically 4 to 1000 (default: 64). Must be at least 2 * m. | HNSW |
numLists | integer | The number of lists to store in the index. Ranges from 1 to 32768 (default: 100). | IVF |
In the following sections, we will demonstrate how to create and use vector indexes.
Insert the following documents containing vector embeddings into a books collection:
<CodeBlock language="js">{InsertData}</CodeBlock>
The field that we're mostly going to focus on is vector, which represents the vector embeddings generated for the summary field using the SentenceTransformer("all-MiniLM-L6-v2") model.
You can use any embedding model to generate the vectors.
To create an HNSW index, set the kind field to vector-hnsw when creating the vector index.
<CodeBlock language="js">{HNSWIndexRequest}</CodeBlock>
</TabItem> <TabItem value="ivf" label="IVF">To create an IVF index, set the kind field to vector-ivf when creating the vector index.
<CodeBlock language="js">{IVFIndexRequest}</CodeBlock>
</TabItem> </Tabs>Once an index is created, you can perform vector searches using the $search stage in the aggregation pipeline:
db.runCommand({
aggregate: 'collectionName',
pipeline: [
{
$search: {
cosmosSearch: {
vector: '<vector>',
path: '<path>',
k: '<k>',
// HNSW only
efSearch: '<efSearch>'
}
}
}
],
cursor: {}
})
A typical vector search query includes the query vector, the path to the field containing the vector, and the number of neighbors to return, as described below:
| Field | Type | Description | Applicable Index |
|---|---|---|---|
cosmosSearch | document | An operator that specifies query parameters (vector, path, k, efSearch, etc.) for the vector search. | All |
vector | array | The vector to search for. | All |
path | string | The path to the field containing the vector. | All |
k | integer | The number of neighbors (results) to return. | All |
efSearch | integer | The number of neighbors or dynamic candidate list to search (default: 40). Must range from 1 to 1000 | HSNW |
Using the same embedding model used for generating the vectors, a query vector is generated for An exciting tale of adventure and exploration at sea.
Next, a vector search is performed on the vector field in the books collection to find the two nearest neighbors of the query vector.
<CodeBlock language="js">{HNSWSearchRequest}</CodeBlock>
The query returns the two nearest neighbors of the query vector.
<CodeBlock language="js">{HNSWSearchResponse}</CodeBlock>
</TabItem> <TabItem value="ivf" label="IVF">Using the embeddings model used for generating the vectors, a query vector is generated for "A science fiction tale exploring the boundaries of human knowledge".
The following aggregation query performs a vector search on the vector field in the books collection:
<CodeBlock language="js">{IVFSearchRequest}</CodeBlock>
By setting returnStoredSource: true, the query returns the similarity score along with matching documents.
Otherwise, only the similarity score is returned, and the actual document content is excluded.
The query returns the two nearest neighbors of the query vector.
<CodeBlock language="js">{IVFSearchResponse}</CodeBlock>
</TabItem> </Tabs>