Back to Ferretdb

Vector search

website/versioned_docs/version-v2.7/guides/vector-search.mdx

2.7.09.4 KB
Original Source

Vector search

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.

Vector indexes

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:

  • Hierarchical Navigable Small World (HNSW): HNSW is a graph-based index that uses a hierarchical structure to store vectors, suitable for high-speed vector search in memory.
  • Inverted File (IVF): IVF is an inverted file index that partitions the vector space (data sets) into clusters (inverted lists) and performs approximate nearest neighbor search within selected clusters.

Creating an index

Vector index can be created using the usual createIndexes command with the following syntax:

js
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:

FieldTypeDescriptionIndex kind
<path>stringThe path to the field containing the vector embeddings. The field must be mapped to "cosmosSearch" to enable creation of a vector index.All
cosmosSearchOptionsdocumentIt specifies the configuration parameters (kind, similarity, dimensions, etc.) for the vector index to suit your specific use caseAll
kindstringThe kind of index to create. Possible values: vector-hnsw, vector-ivf.All
similaritystringThe 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
dimensionsintegerThe number of dimensions in the vector. Note that all vectors in the collection must have the same dimensionality. Must range from 2-16000All
mintegerThe maximum number of connections per layer. Typically range from 2 to 100 (default: 16).HNSW
efConstructionintegerThe 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
numListsintegerThe number of lists to store in the index. Ranges from 1 to 32768 (default: 100).IVF

Index creation example

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.

<Tabs groupId="kind"> <TabItem value="hnsw" label="HNSW" default>

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:

js
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:

FieldTypeDescriptionApplicable Index
cosmosSearchdocumentAn operator that specifies query parameters (vector, path, k, efSearch, etc.) for the vector search.All
vectorarrayThe vector to search for.All
pathstringThe path to the field containing the vector.All
kintegerThe number of neighbors (results) to return.All
efSearchintegerThe number of neighbors or dynamic candidate list to search (default: 40). Must range from 1 to 1000HSNW

Vector search example

<Tabs groupId="kind"> <TabItem value="hnsw" label="HNSW" default>

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>