Vector Search using a Static Index



Indexing a vector field - Overview

Defining a vector field in a static index


To define a vector index-field in your static-index definition:


The source data types that can be used for vector search are detailed in Data types for vector search.

Parameters defined at index definition


The following params can be defined for the vector index-field in the index definition:

Source embedding type -
RavenDB supports performing vector search on TEXTUAL values or NUMERICAL arrays.
This param specifies the embedding format of the source data to be indexed.
Options include Text, Single, Int8, or Binary.

Destination embedding type -
Specify the quantization format for the embeddings that will be generated.
Read more about quantization in Quantization options.

Dimensions -
For numerical input only - define the size of the array from your source document.

  • If this param is Not provided -
    the size will be determined by the first document indexed and will apply to all subsequent documents.

  • Ensure the dimensionality of these numerical arrays (i.e., their length) is consistent across all source documents for the indexed field. An index error will occur if a source document has a different dimension for the indexed field.

Number of edges -
Specify the number of edges that will be created for a vector during indexing.
If not specified, the default value is taken from the following configuration key: Indexing.Corax.VectorSearch.DefaultNumberOfEdges.

Number of candidates for indexing time -
The number of candidates (potential neighboring vectors) that RavenDB evaluates during vector indexing.
If not specified, the default value is taken from the following configuration key: Indexing.Corax.VectorSearch.DefaultNumberOfCandidatesForIndexing.
(Note, this param differs from the number of candidates for query time).

Behavior during indexing


  • Raw textual input:
    When indexing raw textual input from your documents, RavenDB generates embedding vectors using the built-in
    bge-micro-v2 sentence-transformer model, which are then indexed.

  • Pre-made text-embeddings input:
    When indexing embeddings that are pre-generated from your documents' raw text by RavenDB's
    Embeddings generation tasks, RavenDB indexes them without additional transformation, unless quantization is applied.

  • Raw numerical input:
    When indexing pre-made numerical arrays that are already in vector format but were Not generated by these tasks,
    such as numerical arrays you created externally, RavenDB indexes them without additional transformation,
    unless quantization is applied.


The embeddings are indexed on the server using the HNSW algorithm.
This algorithm organizes embeddings into a high-dimensional graph structure,
enabling efficient retrieval of Approximate Nearest Neighbors (ANN) during queries.

Parameters used at query time


Minimum similarity -
You can specify the minimum similarity to use when searching for related vectors. Can be a value between 0.0f and 1.0f.
A value closer to 1.0f requires higher similarity between vectors, while a value closer to 0.0f allows for less similarity.
If not specified, the default value is taken from the following configuration key: Indexing.Corax.VectorSearch.DefaultMinimumSimilarity.

Number of candidates at query time -
You can specify the maximum number of vectors that RavenDB will return from a graph search.
The number of the resulting documents that correspond to these vectors may be:

  • lower than the number of candidates - when multiple vectors originated from the same document.

  • higher than the number of candidates - when the same vector is shared between multiple documents.

If not specified, the default value is taken from the following configuration key: Indexing.Corax.VectorSearch.DefaultNumberOfCandidatesForQuerying.

Search method -
You can specify the search method at query time:

  • Approximate Nearest-Neighbor search (Default):
    Search for related vectors in an approximate manner, providing faster results.

  • Exact search:
    Perform a thorough scan of the vectors to find the actual closest vectors,
    offering better accuracy but at a higher computational cost.


To ensure consistent comparisons -
the search term is transformed into an embedding vector using the same method as the vector index-field.

Search results -
The server will search for the most similar vectors in the indexed vector space, taking into account all the parameters described. The documents that correspond to the resulting vectors are then returned to the client.

By default, the resulting documents will be ordered by their score. You can modify this behavior using the Indexing.Corax.VectorSearch.OrderByScoreAutomatically configuration key.
In addition, you can apply any of the 'order by' methods to your query, as explained in sort query results.

Vector behavior when documents are deleted


  • RavenDB's implementation of the HNSW graph is append-only.

  • When all documents associated with a specific vector are deleted, the vector itself is Not physically removed but is soft-deleted. This means the vector is marked as deleted and will no longer appear in query results.
    Currently, compaction is not supported.

Indexing vector data - TEXT

Indexing raw text

The index in this example indexes data from raw text.
For an index that indexes pre-made text-embeddings see this example below.

This index defines a vector field named VectorfromText.
It indexes embeddings generated from the raw textual data in the Name field of all Product documents.

public class Products_ByVector_Text :
    AbstractIndexCreationTask<Product, Products_ByVector_Text.IndexEntry>
{
    public class IndexEntry()
    {
        // This index-field will hold the embeddings that will be generated
        // from the TEXT in the documents
        public object VectorFromText { get; set; }
    }
    
    public Products_ByVector_Text()
    {
        Map = products => from product in products
            select new IndexEntry
            {
                // Call 'CreateVector' to create a VECTOR FIELD.
                // Pass the document field containing the text
                // from which the embeddings will be generated.
                VectorFromText = CreateVector(product.Name)
            };

        // Customize the vector field options:
        VectorIndexes.Add(x => x.VectorFromText,
            new VectorOptions()
            {
                // Define the source embedding type
                SourceEmbeddingType = VectorEmbeddingType.Text, 
                
                // Define the quantization for the destination embedding
                DestinationEmbeddingType = VectorEmbeddingType.Single,
                
                // Optionally, set the number of edges 
                NumberOfEdges = 20,
                
                // Optionally, set the number of candidates
                NumberOfCandidatesForIndexing = 20
            });

        // The index MUST use the Corax search engine 
        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
public class Products_ByVector_Text_JS : AbstractJavaScriptIndexCreationTask
{
    public Products_ByVector_Text_JS()
    {
        Maps = new HashSet<string>()
        {
            $@"map('Products', function (product) {{
                   return {{
                       VectorFromText: createVector(product.Name)
                   }};
             }})"
        };
    
        Fields = new();
        Fields.Add("VectorFromText", new IndexFieldOptions()
        {
            Vector = new VectorOptions()
            {
                SourceEmbeddingType = VectorEmbeddingType.Text, 
                DestinationEmbeddingType = VectorEmbeddingType.Single,
                NumberOfEdges = 20,
                NumberOfCandidatesForIndexing = 20
            }
        });

        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
var indexDefinition = new IndexDefinition
{
    Name = "Products/ByVector/Text",
    
    Maps = new HashSet<string>
    {
        @"
          from product in docs.Products
          select new 
          {
              VectorFromText  = CreateVector(product.Name)
          }"
    },
    
    Fields = new Dictionary<string, IndexFieldOptions>()
    {
        {
            "VectorFromText",
            new IndexFieldOptions()
            {
                Vector = new VectorOptions()
                {
                    SourceEmbeddingType = VectorEmbeddingType.Text,
                    DestinationEmbeddingType = VectorEmbeddingType.Single,
                    NumberOfEdges = 20,
                    NumberOfCandidatesForIndexing = 20
                }
            }
        }
    },
    
    Configuration = new IndexConfiguration()
    {
        ["Indexing.Static.SearchEngineType"] = "Corax"
    }
};

store.Maintenance.Send(new PutIndexesOperation(indexDefinition));

Execute a vector search using the index:
Results will include Product documents where the Name field is similar to the search term "italian food".

var similarProducts = session
    .Query<Products_ByVector_Text.IndexEntry, Products_ByVector_Text>()
     // Perform a vector search
     // Call the 'VectorSearch' method
    .VectorSearch(
        field => field
             // Call 'WithField'
             // Specify the index-field in which to search for similar values
            .WithField(x => x.VectorFromText),
        searchTerm => searchTerm
             // Call 'ByText'   
             // Provide the term for the similarity comparison
            .ByText("italian food"),
        // Optionally, specify the minimum similarity value
        minimumSimilarity: 0.82f,
        // Optionally, specify the number candidates for querying
        numberOfCandidates: 20,
        // Optionally, specify whether the vector search should use the 'exact search method'
        isExact: true)
     // Waiting for not-stale results is not mandatory
     // but will assure results are not stale
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Product>()
    .ToList();
var similarProducts = await asyncSession
    .Query<Products_ByVector_Text.IndexEntry, Products_ByVector_Text>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromText),
        searchTerm => searchTerm
            .ByText("italian food"), 0.82f, 20, isExact: true)
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Product>()
    .ToListAsync();
var similarProducts = session.Advanced
    .DocumentQuery<Products_ByVector_Text.IndexEntry, Products_ByVector_Text>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromText),
        searchTerm => searchTerm
            .ByText("italian food"), 0.82f, 20, isExact: true)
    .WaitForNonStaleResults()
    .OfType<Product>()
    .ToList();
var similarProducts = await asyncSession.Advanced
    .AsyncDocumentQuery<Products_ByVector_Text.IndexEntry, Products_ByVector_Text>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromText),
        searchTerm => searchTerm
            .ByText("italian food"),
        0.82f, 20, isExact: true)
    .WaitForNonStaleResults()
    .OfType<Product>()
    .ToListAsync();
var similarProducts = session.Advanced
    .RawQuery<Product>(@"
        from index 'Products/ByVector/Text'
        // Optionally, wrap the 'vector.search' query with 'exact()' to perform an exact search
        where exact(vector.search(VectorFromText, $searchTerm, 0.82, 20))")
    .AddParameter("searchTerm", "italian food")
    .WaitForNonStaleResults()
    .ToList();
var similarProducts = await asyncSession.Advanced
    .AsyncRawQuery<Product>(@"
        from index 'Products/ByVector/Text'
        // Optionally, wrap the 'vector.search' query with 'exact()' to perform an exact search
        where exact(vector.search(VectorFromText, $searchTerm, 0.82, 20))")
    .AddParameter("searchTerm", "italian food")
    .WaitForNonStaleResults()
    .ToListAsync();
from index "Products/ByVector/Text"
// Optionally, wrap the 'vector.search' query with 'exact()' to perform an exact search
where exact(vector.search(VectorFromText, $searchTerm, 0.82, 20))
{ "searchTerm" : "italian food" }

Indexing pre-made text-embeddings

The index in this example defines a vector field named VectorfromTextEmbeddings.
It indexes pre-made embeddings that were generated by this embedding generation task.

public class Categories_ByPreMadeTextEmbeddings :
    AbstractIndexCreationTask<Category, Categories_ByPreMadeTextEmbeddings.IndexEntry>
{
    public class IndexEntry()
    {
        // This index-field will hold the text embeddings
        // that were pre-made by the Embeddings Generation Task
        public object VectorFromTextEmbeddings { get; set; }
    }
    
    public Categories_ByPreMadeTextEmbeddings()
    {
        Map = categories => from category in categories
            select new IndexEntry
            {
                // Call 'LoadVector' to create a VECTOR FIELD. Pass:
                // * The document field name to be indexed (as a string) 
                // * The identifier of the task that generated the embeddings
                //   for the 'Name' field
                VectorFromTextEmbeddings = LoadVector("Name", "id-for-task-open-ai")
            };

        VectorIndexes.Add(x => x.VectorFromTextEmbeddings,
            new VectorOptions()
            {
               // Vector options can be customized
               // in the same way as the above index example.
            });
        
        // The index MUST use the Corax search engine 
        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
public class Categories_ByPreMadeTextEmbeddings_JS : AbstractJavaScriptIndexCreationTask
{
    public Categories_ByPreMadeTextEmbeddings_JS()
    {
        Maps = new HashSet<string>()
        {
            $@"map('Categories', function (category) {{
                   return {{
                       VectorFromTextEmbeddings:
                           loadVector('Name', 'id-for-task-open-ai')
                   }};
             }})"
        };
    
        Fields = new();
        Fields.Add("VectorFromTextEmbeddings", new IndexFieldOptions()
        {
            Vector = new VectorOptions()
            {
                // Vector options can be customized
                // in the same way as the above index example.
            }
        });

        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
var indexDefinition = new IndexDefinition
{
    Name = "Categories/ByPreMadeTextEmbeddings",
    Maps = new HashSet<string>
    {
        @"
          from category in docs.Categories
          select new 
          {
              VectorFromTextEmbeddings = LoadVector(""Name"", ""id-for-task-open-ai"")
          }"
    },
    
    Fields = new Dictionary<string, IndexFieldOptions>()
    {
        {
            "VectorFromTextEmbeddings",
            new IndexFieldOptions()
            {
                Vector = new VectorOptions()
                {
                    // Vector options can be customized
                    // in the same way as the above index example.
                }
            }
        }
    },
    
    Configuration = new IndexConfiguration()
    {
        ["Indexing.Static.SearchEngineType"] = "Corax"
    }
};

store.Maintenance.Send(new PutIndexesOperation(indexDefinition));

Execute a vector search using the index:
Results will include Category documents where the Name field is similar to the search term "candy".

var similarCategories = session
    .Query<Categories_ByPreMadeTextEmbeddings.IndexEntry, Categories_ByPreMadeTextEmbeddings>()
    // Perform a vector search
    // Call the 'VectorSearch' method
    .VectorSearch(
        field => field
            // Call 'WithField'
            // Specify the index-field in which to search for similar values
            .WithField(x => x.VectorFromTextEmbeddings),
        searchTerm => searchTerm
            // Call 'ByText'
            // Provide the search term for the similarity comparison
            .ByText("candy"),
        // Optionally, specify the minimum similarity value
        minimumSimilarity: 0.75f,
        // Optionally, specify the number of candidates for querying
        numberOfCandidates: 20,
        // Optionally, specify whether the vector search should use the 'exact search method'
        isExact: true)
    // Waiting for not-stale results is not mandatory
    // but will assure results are not stale
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Category>()
    .ToList();
var similarCategories = await asyncSession
    .Query<Categories_ByPreMadeTextEmbeddings.IndexEntry, Categories_ByPreMadeTextEmbeddings>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromTextEmbeddings),
        searchTerm => searchTerm
            .ByText("candy"), 0.75f, 20, isExact: true)
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Category>()
    .ToListAsync();
var similarCategories = session.Advanced
    .DocumentQuery<Categories_ByPreMadeTextEmbeddings.IndexEntry, Categories_ByPreMadeTextEmbeddings>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromTextEmbeddings),
        searchTerm => searchTerm
            .ByText("candy"), 0.75f, 20, isExact: true)
    .WaitForNonStaleResults()
    .OfType<Category>()
    .ToList();
var similarCategories = await asyncSession.Advanced
    .AsyncDocumentQuery<Categories_ByPreMadeTextEmbeddings.IndexEntry, Categories_ByPreMadeTextEmbeddings>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromTextEmbeddings),
        searchTerm => searchTerm
            .ByText("candy"),
        0.75f, 20, isExact: true)
    .WaitForNonStaleResults()
    .OfType<Category>()
    .ToListAsync();
var similarCategories = session.Advanced
    .RawQuery<Category>(@"
        from index 'Categories/ByPreMadeTextEmbeddings'
        // Optionally, wrap the 'vector.search' query with 'exact()' to perform an exact search
        where exact(vector.search(VectorFromTextEmbeddings, $searchTerm, 0.75, 20))")
    .AddParameter("searchTerm", "candy")
    .WaitForNonStaleResults()
    .ToList();
var similarCategories = await asyncSession.Advanced
    .AsyncRawQuery<Category>(@"
        from index 'Categories/ByPreMadeTextEmbeddings'
        // Optionally, wrap the 'vector.search' query with 'exact()' to perform an exact search
        where exact(vector.search(VectorFromTextEmbeddings, $searchTerm, 0.75, 20))")
    .AddParameter("searchTerm", "candy")
    .WaitForNonStaleResults()
    .ToListAsync();
from index "Categories/ByPreMadeTextEmbeddings"
// Optionally, wrap the 'vector.search' query with 'exact()' to perform an exact search
where exact(vector.search(VectorFromTextEmbeddings, $p0, 0.75, 20))
{ "p0": "candy" }

Indexing vector data - NUMERICAL

The examples in this section use the sample data provided in the dynamic query article.


The following index defines a vector field named VectorFromSingle.
It indexes embeddings generated from the numerical data in the TagsEmbeddedAsSingle field of all Movie documents. The raw numerical data in the source documents is in 32-bit floating-point format.

public class Movies_ByVector_Single :
    AbstractIndexCreationTask<Movie, Movies_ByVector_Single.IndexEntry>
{
    public class IndexEntry()
    {
        // This index-field will hold the embeddings that will be generated
        // from the NUMERICAL content in the documents.
        public object VectorFromSingle { get; set; }
    }
    
    public Movies_ByVector_Single()
    {
        Map = movies => from movie in movies
            select new IndexEntry
            {
                // Call 'CreateVector' to create a VECTOR FIELD.
                // Pass the document field containing the array (32-bit floating-point values)
                // from which the embeddings will be generated.
                VectorFromSingle = CreateVector(movie.TagsEmbeddedAsSingle)
            };

        // Customize the vector field options:
        VectorIndexes.Add(x => x.VectorFromSingle,
            new VectorOptions()
            {
                // Define the source embedding type
                SourceEmbeddingType = VectorEmbeddingType.Single,
                
                // Define the quantization for the destination embedding
                DestinationEmbeddingType = VectorEmbeddingType.Single,
                
                // It is recommended to configure the number of dimensions
                // which is the size of the arrays that will be indexed.
                Dimensions = 2,
                
                // Optionally, set the number of edges and candidates
                NumberOfEdges = 20,
                NumberOfCandidatesForIndexing = 20
            });

        // The index MUST use the Corax search engine 
        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
public class Movies_ByVector_Single_JS : AbstractJavaScriptIndexCreationTask
{
    public Movies_ByVector_Single_JS()
    {
        Maps = new HashSet<string>()
        {
            $@"map('Movies', function (movie) {{
                   return {{
                       VectorFromSingle: createVector(movie.TagsEmbeddedAsSingle)
                   }};
             }})"
        };
    
        Fields = new();
        Fields.Add("VectorFromSingle", new IndexFieldOptions()
        {
            Vector = new VectorOptions()
            {
                SourceEmbeddingType = VectorEmbeddingType.Single, 
                DestinationEmbeddingType = VectorEmbeddingType.Single,
                Dimensions = 2,
                NumberOfEdges = 20,
                NumberOfCandidatesForIndexing = 20
            }
        });

        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
var indexDefinition = new IndexDefinition 
{
    Name = "Movies/ByVector/Single",

    Maps = new HashSet<string>
    {
        @"
          from movie in docs.Movies
          select new 
          {
              VectorFromSingle = CreateVector(movie.TagsEmbeddedAsSingle)
          }"
    },
    
    Fields = new Dictionary<string, IndexFieldOptions>()
    {
        {
            "VectorFromSingle",
            new IndexFieldOptions()
            {
                Vector = new VectorOptions()
                {
                    SourceEmbeddingType = VectorEmbeddingType.Single,
                    DestinationEmbeddingType = VectorEmbeddingType.Single,
                    Dimensions = 2,
                    NumberOfEdges = 20,
                    NumberOfCandidatesForIndexing = 20
                }
            }
        }
    },
    
    Configuration = new IndexConfiguration()
    {
        ["Indexing.Static.SearchEngineType"] = "Corax"
    }
};

store.Maintenance.Send(new PutIndexesOperation(indexDefinition));

Execute a vector search using the index:

var similarMovies = session
    .Query<Movies_ByVector_Single.IndexEntry, Movies_ByVector_Single>()
     // Perform a vector search
     // Call the 'VectorSearch' method
    .VectorSearch(
        field => field
             // Call 'WithField'
             // Specify the index-field in which to search for similar values
            .WithField(x => x.VectorFromSingle),
        queryVector => queryVector
             // Call 'ByEmbedding'   
             // Provide the vector for the similarity comparison
            .ByEmbedding(
                 new RavenVector<float>(new float[] { 6.599999904632568f, 7.699999809265137f })))
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Movie>()
    .ToList();
var similarMovies = await asyncSession
    .Query<Movies_ByVector_Single.IndexEntry, Movies_ByVector_Single>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromSingle),
        queryVector => queryVector
            .ByEmbedding(
                new RavenVector<float>(new float[] { 6.599999904632568f, 7.699999809265137f })))
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Movie>()
    .ToListAsync();
var similarMovies = session.Advanced
    .DocumentQuery<Movies_ByVector_Single.IndexEntry, Movies_ByVector_Single>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromSingle),
        queryVector => queryVector
            .ByEmbedding(
                new RavenVector<float>(new float[] { 6.599999904632568f, 7.699999809265137f })))
    .WaitForNonStaleResults()
    .OfType<Movie>()
    .ToList();
var similarMovies = await asyncSession.Advanced
    .AsyncDocumentQuery<Movies_ByVector_Single.IndexEntry, Movies_ByVector_Single>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromSingle),
        queryVector => queryVector
            .ByEmbedding(
                new RavenVector<float>(new float[] { 6.599999904632568f, 7.699999809265137f })))
    .WaitForNonStaleResults()
    .OfType<Movie>()
    .ToListAsync();
var similarMovies = session.Advanced
    .RawQuery<Movie>(@"
        from index 'Movies/ByVector/Single'
        where vector.search(VectorFromSingle, $queryVector)")
    .AddParameter("queryVector", new RavenVector<float>(new float[]
     {
         6.599999904632568f, 7.699999809265137f
     }))
    .WaitForNonStaleResults()
    .ToList();
var similarMovies = await asyncSession.Advanced
    .AsyncRawQuery<Movie>(@"
        from index 'Movies/ByVector/Single'
        where vector.search(VectorFromSingle, $queryVector)")
    .AddParameter("queryVector", new RavenVector<float>(new float[]
     {
         6.599999904632568f, 7.699999809265137f
     }))
    .WaitForNonStaleResults()
    .ToListAsync();
from index "Movies/ByVector/Single"
where vector.search(VectorFromSingle, $queryVector)
{ "queryVector" : { "@vector" : [6.599999904632568, 7.699999809265137] }}

The following index defines a vector field named VectorFromInt8Arrays.
It indexes embeddings generated from the numerical arrays in the TagsEmbeddedAsInt8 field of all Movie documents. The raw numerical data in the source documents is in Int8 (8-bit integers) format.

public class Movies_ByVector_Int8 :
    AbstractIndexCreationTask<Movie, Movies_ByVector_Int8.IndexEntry>
{
    public class IndexEntry()
    {
        // This index-field will hold the embeddings that will be generated
        // from the NUMERICAL content in the documents.
        public object VectorFromInt8Arrays { get; set; }
    }
    
    public Movies_ByVector_Int8()
    {
        Map = movies => from movie in movies
            select new IndexEntry
            {
                // Call 'CreateVector' to create a VECTOR FIELD.
                // Pass the document field containing the arrays (8-bit integer values)
                // from which the embeddings will be generated.
                VectorFromInt8Arrays = CreateVector(movie.TagsEmbeddedAsInt8)
            };

        // Customize the vector field options:
        VectorIndexes.Add(x => x.VectorFromInt8Arrays,
            new VectorOptions()
            {
                // Define the source embedding type
                SourceEmbeddingType = VectorEmbeddingType.Int8,
                
                // Define the quantization for the destination embedding
                DestinationEmbeddingType = VectorEmbeddingType.Int8,
                
                // It is recommended to configure the number of dimensions
                // which is the size of the arrays that will be indexed.
                Dimensions = 2,
                
                // Optionally, set the number of edges and candidates
                NumberOfEdges = 20,
                NumberOfCandidatesForIndexing = 20
            });

        // The index MUST use the Corax search engine 
        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
public class Movies_ByVector_Int8_JS : AbstractJavaScriptIndexCreationTask
{
    public Movies_ByVector_Int8_JS()
    {
        Maps = new HashSet<string>()
        {
            $@"map('Movies', function (movie) {{
                   return {{
                       VectorFromInt8Arrays: createVector(movie.TagsEmbeddedAsInt8)
                   }};
             }})"
        };
    
        Fields = new();
        Fields.Add("VectorFromInt8Arrays", new IndexFieldOptions()
        {
            Vector = new VectorOptions()
            {
                SourceEmbeddingType = VectorEmbeddingType.Int8, 
                DestinationEmbeddingType = VectorEmbeddingType.Int8,
                Dimensions = 2,
                NumberOfEdges = 20,
                NumberOfCandidatesForIndexing = 20
            }
        });

        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
var indexDefinition = new IndexDefinition 
{
    Name = "Movies/ByVector/Int8",

    Maps = new HashSet<string>
    {
        @"
          from movie in docs.Movies
          select new 
          {
              VectorFromInt8Arrays = CreateVector(movie.TagsEmbeddedAsInt8)
          }"
    },
    
    Fields = new Dictionary<string, IndexFieldOptions>()
    {
        {
            "VectorFromInt8Arrays",
            new IndexFieldOptions()
            {
                Vector = new VectorOptions()
                {
                    SourceEmbeddingType = VectorEmbeddingType.Int8,
                    DestinationEmbeddingType = VectorEmbeddingType.Int8,
                    Dimensions = 2,
                    NumberOfEdges = 20,
                    NumberOfCandidatesForIndexing = 20
                }
            }
        }
    },
    
    Configuration = new IndexConfiguration()
    {
        ["Indexing.Static.SearchEngineType"] = "Corax"
    }
};

store.Maintenance.Send(new PutIndexesOperation(indexDefinition));

Execute a vector search using the index:

var similarMovies = session
    .Query<Movies_ByVector_Int8.IndexEntry, Movies_ByVector_Int8>()
     // Perform a vector search
     // Call the 'VectorSearch' method
    .VectorSearch(
        field => field
             // Call 'WithField'
             // Specify the index-field in which to search for similar values
            .WithField(x => x.VectorFromInt8Arrays),
        queryVector => queryVector
             // Call 'ByEmbedding'   
             // Provide the vector for the similarity comparison
             // (Note: provide a single vector)
            .ByEmbedding(
                // The provided vector MUST be in the same format as was stored in your document
                // Call 'VectorQuantizer.ToInt8' to transform the rawData to the Int8 format 
                VectorQuantizer.ToInt8(new float[] { 0.1f, 0.2f })))
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Movie>()
    .ToList();
var similarMovies = await asyncSession
    .Query<Movies_ByVector_Int8.IndexEntry, Movies_ByVector_Int8>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromInt8Arrays),
        queryVector => queryVector
            .ByEmbedding(
                VectorQuantizer.ToInt8(new float[] { 0.1f, 0.2f })))
    .Customize(x => x.WaitForNonStaleResults())
    .OfType<Movie>()
    .ToListAsync();
var similarMovies = session.Advanced
    .DocumentQuery<Movies_ByVector_Int8.IndexEntry, Movies_ByVector_Int8>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromInt8Arrays),
        queryVector => queryVector
            .ByEmbedding(
                VectorQuantizer.ToInt8(new float[] { 0.1f, 0.2f })))
    .WaitForNonStaleResults()
    .OfType<Movie>()
    .ToList();
var similarMovies = await asyncSession.Advanced
    .AsyncDocumentQuery<Movies_ByVector_Int8.IndexEntry, Movies_ByVector_Int8>()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromInt8Arrays),
        queryVector => queryVector
            .ByEmbedding(
                VectorQuantizer.ToInt8(new float[] { 0.1f, 0.2f })))
    .WaitForNonStaleResults()
    .OfType<Movie>()
    .ToListAsync();
var similarMovies = session.Advanced
    .RawQuery<Movie>(@"
        from index 'Movies/ByVector/Int8'
        where vector.search(VectorFromInt8Arrays, $queryVector)")
    .AddParameter("queryVector", VectorQuantizer.ToInt8(new float[] { 0.1f, 0.2f }))
    .WaitForNonStaleResults()
    .ToList();
var similarMovies = await asyncSession.Advanced
    .AsyncRawQuery<Movie>(@"
        from index 'Movies/ByVector/Int8'
        where vector.search(VectorFromInt8Arrays, $queryVector)")
    .AddParameter("queryVector", VectorQuantizer.ToInt8(new float[] { 0.1f, 0.2f }))
    .WaitForNonStaleResults()
    .ToListAsync();
from index "Movies/ByVector/Int8"
where vector.search(VectorFromInt8Arrays, $queryVector)
{ "queryVector" : [64, 127, -51, -52, 76, 62] }

Indexing multiple field types

An index can define multiple types of index-fields. In this example, the index includes:
A 'regular' field, a 'vector' field, and a field configured for full-text search.
This allows you to query across all fields using various predicates.

public class Products_ByMultipleFields :
    AbstractIndexCreationTask<Product, Products_ByMultipleFields.IndexEntry>
{
    public class IndexEntry()
    {
        // An index-field for 'regular' data
        public decimal PricePerUnit { get; set; }
        
        // An index-field for 'full-text' search
        public string Name { get; set; }
        
        // An index-field for 'vector' search
        public object VectorFromText { get; set; }
    }
    
    public Products_ByMultipleFields()
    {
        Map = products => from product in products
            select new IndexEntry
            {
                PricePerUnit = product.PricePerUnit,
                Name = product.Name,
                VectorFromText = CreateVector(product.Name)
            };
        
        // Configure the index-field 'Name' for FTS:
        Index(x => x.Name, FieldIndexing.Search);
        
        // Note:
        // Default values will be used for the VECTOR FIELD if not customized here.
        
        // The index MUST use the Corax search engine 
        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
public class Products_ByMultipleFields_JS : AbstractJavaScriptIndexCreationTask
{
    public Products_ByMultipleFields_JS()
    {
        Maps = new HashSet<string>()
        {
            $@"map('Products', function (product) {{
                   return {{
                       PricePerUnit: product.PricePerUnit,
                       Name: product.Name,
                       VectorFromText: createVector(product.Name)
                   }};
             }})"
        };
    
        Fields = new();
        Fields.Add("Name", new IndexFieldOptions()
        {
            Indexing = FieldIndexing.Search
        });

        SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
    }
}
var indexDefinition = new IndexDefinition
{
    Name = "Products/ByMultipleFields",
    Maps = new HashSet<string>
    {
        @"
          from product in docs.Products
          select new 
          {
              PricePerUnit = product.PricePerUnit,
              Name = product.Name,
              VectorFromText  = CreateVector(product.Name)
          }"
    },
    
    Fields = new Dictionary<string, IndexFieldOptions>()
    {
        {
            "Name",
            new IndexFieldOptions()
            {
                Indexing = FieldIndexing.Search
            }
        }
    },
    
    Configuration = new IndexConfiguration()
    {
        ["Indexing.Static.SearchEngineType"] = "Corax"
    }
};

store.Maintenance.Send(new PutIndexesOperation(indexDefinition));

Execute a query that combines predicates across all index-field types:

var results = session.Advanced
    .DocumentQuery<Products_ByMultipleFields.IndexEntry, Products_ByMultipleFields>()
     // Perform a regular search
    .WhereGreaterThan(x => x.PricePerUnit, 200)
    .OrElse()
     // Perform a full-text search
    .Search(x => x.Name, "Alice")
    .OrElse()
     // Perform a vector search
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromText),
        searchTerm => searchTerm
            .ByText("italian food"),
        minimumSimilarity: 0.8f)
    .WaitForNonStaleResults()
    .OfType<Product>()
    .ToList();
var results = await asyncSession.Advanced
    .AsyncDocumentQuery<Products_ByMultipleFields.IndexEntry, Products_ByMultipleFields>()
    .WhereGreaterThan(x => x.PricePerUnit, 200)
    .OrElse()
    .Search(x => x.Name, "Alice")
    .OrElse()
    .VectorSearch(
        field => field
            .WithField(x => x.VectorFromText),
        searchTerm => searchTerm
            .ByText("italian food"),
        minimumSimilarity: 0.8f)
    .WaitForNonStaleResults()
    .OfType<Product>()
    .ToListAsync();
var results = session.Advanced
    .RawQuery<Product>(@"
        from index 'Products/ByMultipleFields'
        where PricePerUnit > $minPrice
        or search(Name, $searchTerm1)
        or vector.search(VectorFromText, $searchTerm2, 0.8)")
    .AddParameter("minPrice", 200)
    .AddParameter("searchTerm1", "Alice")
    .AddParameter("searchTerm2", "italian")
    .WaitForNonStaleResults()
    .ToList();
var results = await asyncSession.Advanced
    .AsyncRawQuery<Product>(@"
        from index 'Products/ByMultipleFields'
        where PricePerUnit > $minPrice
        or search(Name, $searchTerm1)
        or vector.search(VectorFromText, $searchTerm2, 0.8)")
    .AddParameter("minPrice", 200)
    .AddParameter("searchTerm1", "Alice")
    .AddParameter("searchTerm2", "italian")
    .WaitForNonStaleResults()
    .ToListAsync();
from index "Products/ByMultipleFields"
where PricePerUnit > $minPrice
or search(Name, $searchTerm1)
or vector.search(VectorFromText, $searchTerm2, 0.8)
{ "minPrice" : 200, "searchTerm1" : "Alice", "searchTerm2": "italian" }

Configure the vector field in the Studio

Add vector field

Add vector field

Customize vector field

Customize vector field

  1. Vector field name
    Enter the name of the vector field to customize.
  2. Configure Vector Field
    Click this button to customize the field.
  3. Dimensions
    For numerical input only - define the size of the array from your source document.
  4. Edges
    The number of edges that will be created for a vector during indexing.
  5. Source embedding type
    The format of the source embeddings (Text, Single, Int8, or Binary).
  6. Candidates for indexing
    The number of candidates (potential neighboring vectors) that RavenDB evaluates during vector indexing.
  7. Destination embedding type
    The quantization format for the embeddings that will be generated (Text, Single, Int8, or Binary).