Indexing Attachments for Vector Search
-
This article explains how to index attachments using a static-index to enable vector search on their content.
Note: Vector search on attachment content is not available when making a dynamic query. -
Prior to this article, refer to the Vector search using a static index article for general knowledge about
indexing a vector field. -
In this article:
Overview
Attachments in RavenDB
-
Attachments in RavenDB allow you to associate binary files with your JSON documents.
You can use attachments to store images, PDFs, videos, text files, or any other format. -
Attachments are stored separately from documents, reducing document size and avoiding unnecessary duplication. They are stored as binary data, regardless of content type.
-
Attachments are handled as streams, allowing efficient upload and retrieval.
Learn more in: What are attachments.
Indexing attachment content for vector search
You can index attachment content in a vector field within a static-index,
enabling vector search on text or numerical data that is stored in the attachments:
-
Attachments with TEXT:
- During indexing, RavenDB processes the text into a single embedding per attachment using the built-in
bge-micro-v2 model.
- During indexing, RavenDB processes the text into a single embedding per attachment using the built-in
-
Attachments with NUMERICAL data:
- While attachments can store any file type, RavenDB does Not generate embeddings from images, videos, or other non-textual content.
Each attachment must contain a single precomputed embedding vector, generated externally. - RavenDB indexes the embedding vector from the attachment in and can apply quantization (e.g., index it in Int8 format) if this is configured.
- All embeddings indexed within the same vector-field in the static-index must be vectors of the same dimension to ensure consistency in indexing and search. They must also be created using the same model.
- While attachments can store any file type, RavenDB does Not generate embeddings from images, videos, or other non-textual content.
Indexing TEXT attachments
-
The following index defines a vector field named
VectorFromAttachment
. -
It indexes embeddings generated from the text content of the
description.txt
attachment.
This applies to all Company documents that contain an attachment with that name.
public class Companies_ByVector_FromTextAttachment :
AbstractIndexCreationTask<Company, Companies_ByVector_FromTextAttachment.IndexEntry>
{
public class IndexEntry()
{
// This index-field will hold embeddings
// generated from the TEXT in the attachments.
public object VectorFromAttachment { get; set; }
}
public Companies_ByVector_FromTextAttachment()
{
Map = companies => from company in companies
// Load the attachment from the document (ensure it is not null)
let attachment = LoadAttachment(company, "description.txt")
where attachment != null
select new IndexEntry()
{
// Index the text content from the attachment in the vector field
VectorFromAttachment =
CreateVector(attachment.GetContentAsString(Encoding.UTF8))
};
// Configure the vector field:
VectorIndexes.Add(x => x.VectorFromAttachment,
new VectorOptions()
{
// Specify 'Text' as the source format
SourceEmbeddingType = VectorEmbeddingType.Text,
// Specify the desired destination format within the index
DestinationEmbeddingType = VectorEmbeddingType.Single
});
SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
}
}
public class Companies_ByVector_FromTextAttachment_JS :
AbstractJavaScriptIndexCreationTask
{
public Companies_ByVector_FromTextAttachment_JS()
{
Maps = new HashSet<string>
{
$@"map('Companies', function (company) {{
var attachment = loadAttachment(company, 'description.txt');
if (!attachment) return null;
return {{
VectorFromAttachment: createVector(attachment.getContentAsString('utf8'))
}};
}})"
};
Fields = new Dictionary<string, IndexFieldOptions>()
{
{
"VectorFromAttachment",
new IndexFieldOptions()
{
Vector = new()
{
SourceEmbeddingType = VectorEmbeddingType.Text,
DestinationEmbeddingType = VectorEmbeddingType.Single
}
}
}
};
SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
}
}
var indexDefinition = new IndexDefinition
{
Name = "Companies/ByVector/FromTextAttachment",
Maps = new HashSet<string>
{
@"from company in docs.Companies
let attachment = LoadAttachment(company, ""description.txt"")
where attachment != null
select new
{
VectorFromAttachment =
CreateVector(attachment.GetContentAsString(Encoding.UTF8))
}"
},
Fields = new Dictionary<string, IndexFieldOptions>()
{
{
"VectorFromAttachment",
new IndexFieldOptions()
{
Vector = new VectorOptions()
{
SourceEmbeddingType = VectorEmbeddingType.Text,
DestinationEmbeddingType = VectorEmbeddingType.Single
}
}
}
},
Configuration = new IndexConfiguration()
{
["Indexing.Static.SearchEngineType"] = "Corax"
}
};
store.Maintenance.Send(new PutIndexesOperation(indexDefinition));
// Prepare text as `byte[]` to be stored as attachments:
// =====================================================
var byteArray1 = Encoding.UTF8.GetBytes(
"Supplies soft drinks, fruit juices, and flavored syrups to restaurants and retailers.");
var byteArray2 = Encoding.UTF8.GetBytes(
"Supplies fine dining restaurants with premium meats, cheeses, and wines across France.");
var byteArray3 = Encoding.UTF8.GetBytes(
"An American grocery chain known for its fresh produce, organic foods, and local meats.");
var byteArray4 = Encoding.UTF8.GetBytes(
"An Asian grocery store specializing in ingredients for Japanese and Thai cuisine.");
var byteArray5 = Encoding.UTF8.GetBytes(
"A rural general store offering homemade jams, fresh-baked bread, and locally crafted gifts.");
using (var session = store.OpenSession())
{
// Load existing Company documents from RavenDB's sample data:
// ===========================================================
var company1 = session.Load<Company>("companies/11-A");
var company2 = session.Load<Company>("companies/26-A");
var company3 = session.Load<Company>("companies/32-A");
var company4 = session.Load<Company>("companies/41-A");
var company5 = session.Load<Company>("companies/43-A");
// Store the attachments in the documents (using MemoryStream):
// ============================================================
session.Advanced.Attachments.Store(company1, "description.txt",
new MemoryStream(byteArray1), "text/plain");
session.Advanced.Attachments.Store(company2, "description.txt",
new MemoryStream(byteArray2), "text/plain");
session.Advanced.Attachments.Store(company3, "description.txt",
new MemoryStream(byteArray3), "text/plain");
session.Advanced.Attachments.Store(company4, "description.txt",
new MemoryStream(byteArray4), "text/plain");
session.Advanced.Attachments.Store(company5, "description.txt",
new MemoryStream(byteArray5), "text/plain");
session.SaveChanges();
}
Execute a vector search using the index:
Results will include Company documents whose attachment contains text similar to "chinese food"
.
var relevantCompanies = session
.Query<Companies_ByVector_FromTextAttachment.IndexEntry,
Companies_ByVector_FromTextAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
searchTerm => searchTerm
.ByText("chinese food"), 0.8f)
.Customize(x => x.WaitForNonStaleResults())
.OfType<Company>()
.ToList();
var relevantCompanies = await asyncSession
.Query<Companies_ByVector_FromTextAttachment.IndexEntry,
Companies_ByVector_FromTextAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
searchTerm => searchTerm
.ByText("chinese food"), 0.8f)
.Customize(x => x.WaitForNonStaleResults())
.OfType<Company>()
.ToListAsync();
var relevantCompanies = session.Advanced
.DocumentQuery<Companies_ByVector_FromTextAttachment.IndexEntry,
Companies_ByVector_FromTextAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
searchTerm => searchTerm
.ByText("chinese food"), 0.8f)
.WaitForNonStaleResults()
.OfType<Company>()
.ToList();
var relevantCompanies = await asyncSession.Advanced
.AsyncDocumentQuery<Companies_ByVector_FromTextAttachment.IndexEntry,
Companies_ByVector_FromTextAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
searchTerm => searchTerm
.ByText("chinese food"), 0.8f)
.WaitForNonStaleResults()
.OfType<Company>()
.ToListAsync();
var relevantCompanies = session.Advanced
.RawQuery<Company>(@"
from index 'Companies/ByVector/FromTextAttachment'
where vector.search(VectorFromAttachment, $searchTerm, 0.8)")
.AddParameter("searchTerm", "chinese food")
.WaitForNonStaleResults()
.ToList();
var relevantCompanies = await asyncSession.Advanced
.AsyncRawQuery<Company>(@"
from index 'Companies/ByVector/FromTextAttachment'
where vector.search(VectorFromAttachment, $searchTerm, 0.8)")
.AddParameter("searchTerm", "chinese food")
.WaitForNonStaleResults()
.ToListAsync();
from index "Companies/ByVector/FromTextAttachment"
where vector.search(VectorFromAttachment, $searchTerm, 0.8)
{ "searchTerm" : "chinese food" }
You can now extract the text from the attachments of the resulting documents:
// Extract text from the attachment of the first resulting document
// ================================================================
// Retrieve the attachment stream
var company = relevantCompanies[0];
var attachmentResult = session.Advanced.Attachments.Get(company, "description.txt");
var attStream = attachmentResult.Stream;
// Read the attachment content into memory and decode it as a UTF-8 string
var ms = new MemoryStream();
attStream.CopyTo(ms);
string attachmentText = Encoding.UTF8.GetString(ms.ToArray());
Indexing NUMERICAL attachments
LINQ index
-
The following index defines a vector field named
VectorFromAttachment
. -
It indexes embeddings generated from the numerical data stored in the
vector.raw
attachment.
This applies to all Company documents that contain an attachment with that name. -
Each attachment contains raw numerical data in 32-bit floating-point format.
public class Companies_ByVector_FromNumericalAttachment :
AbstractIndexCreationTask<Company, Companies_ByVector_FromNumericalAttachment.IndexEntry>
{
public class IndexEntry()
{
// This index-field will hold embeddings
// generated from the NUMERICAL content in the attachments.
public object VectorFromAttachment { get; set; }
}
public Companies_ByVector_FromNumericalAttachment()
{
Map = companies => from company in companies
// Load the attachment from the document (ensure it is not null)
let attachment = LoadAttachment(company, "vector.raw")
where attachment != null
select new IndexEntry
{
// Index the attachment's content in the vector field
VectorFromAttachment = CreateVector(attachment.GetContentAsStream())
};
// Configure the vector field:
VectorIndexes.Add(x => x.VectorFromAttachment,
new VectorOptions()
{
// Define the source embedding type
SourceEmbeddingType = VectorEmbeddingType.Single,
// Define the desired destination format within the index
DestinationEmbeddingType = VectorEmbeddingType.Single
});
SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
}
}
var indexDefinition = new IndexDefinition
{
Name = "Companies/ByVector/FromNumericalAttachment",
Maps = new HashSet<string>
{
@"from company in docs.Companies
let attachment = LoadAttachment(company, ""vector.raw"")
where attachment != null
select new
{
VectorFromAttachment = CreateVector(attachment.GetContentAsStream())
}"
},
Fields = new Dictionary<string, IndexFieldOptions>()
{
{
"VectorFromAttachment",
new IndexFieldOptions()
{
Vector = new VectorOptions()
{
SourceEmbeddingType = VectorEmbeddingType.Single,
DestinationEmbeddingType = VectorEmbeddingType.Single
}
}
}
},
Configuration = new IndexConfiguration()
{
["Indexing.Static.SearchEngineType"] = "Corax"
}
};
store.Maintenance.Send(new PutIndexesOperation(indexDefinition));
// These vectors are simple pre-computed embedding vectors with 32-bit floating-point values.
// Note: In a real scenario, embeddings would be generated by a model.
// ==========================================================================================
var v1 = new float[] { 0.1f, 0.2f, 0.3f, 0.4f };
var v2 = new float[] { 0.1f, 0.7f, 0.8f, 0.9f };
var v3 = new float[] { 0.5f, 0.6f, 0.7f, 0.8f };
// Prepare the embedding vectors as `byte[]` to be stored as attachments:
// =====================================================================
var byteArray1 = MemoryMarshal.Cast<float, byte>(v1).ToArray();
var byteArray2 = MemoryMarshal.Cast<float, byte>(v2).ToArray();
var byteArray3 = MemoryMarshal.Cast<float, byte>(v3).ToArray();
using (var session = store.OpenSession())
{
// Load existing Company documents from RavenDB's sample data:
// ===========================================================
var company1 = session.Load<Company>("companies/50-A");
var company2 = session.Load<Company>("companies/51-A");
var company3 = session.Load<Company>("companies/52-A");
// Store the attachments in the documents (using MemoryStream):
// ============================================================
session.Advanced.Attachments.Store(company1, "vector.raw", new MemoryStream(byteArray1));
session.Advanced.Attachments.Store(company2, "vector.raw", new MemoryStream(byteArray2));
session.Advanced.Attachments.Store(company3, "vector.raw", new MemoryStream(byteArray3));
session.SaveChanges();
}
Execute a vector search using the index:
Results will include Company documents whose attachment contains vectors similar to the query vector.
var similarCompanies = session
.Query<Companies_ByVector_FromNumericalAttachment.IndexEntry,
Companies_ByVector_FromNumericalAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { 0.1f, 0.2f, 0.3f, 0.4f }))
.Customize(x => x.WaitForNonStaleResults())
.OfType<Company>()
.ToList();
var similarCompanies = await asyncSession
.Query<Companies_ByVector_FromNumericalAttachment.IndexEntry,
Companies_ByVector_FromNumericalAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { 0.1f, 0.2f, 0.3f, 0.4f }))
.Customize(x => x.WaitForNonStaleResults())
.OfType<Company>()
.ToListAsync();
var similarCompanies = session.Advanced
.DocumentQuery<Companies_ByVector_FromNumericalAttachment.IndexEntry,
Companies_ByVector_FromNumericalAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { 0.1f, 0.2f, 0.3f, 0.4f }))
.WaitForNonStaleResults()
.OfType<Company>()
.ToList();
var similarCompanies = await asyncSession.Advanced
.AsyncDocumentQuery<Companies_ByVector_FromNumericalAttachment.IndexEntry,
Companies_ByVector_FromNumericalAttachment>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { 0.1f, 0.2f, 0.3f, 0.4f }))
.WaitForNonStaleResults()
.OfType<Company>()
.ToListAsync();
var similarCompanies = session.Advanced
.RawQuery<Company>(@"
from index 'Companies/ByVector/FromNumericalAttachment'
where vector.search(VectorFromAttachment, $queryVector)")
.AddParameter("queryVector", new float[] { 0.1f, 0.2f, 0.3f, 0.4f })
.WaitForNonStaleResults()
.ToList();
var similarCompanies = await asyncSession.Advanced
.AsyncRawQuery<Company>(@"
from index 'Companies/ByVector/FromNumericalAttachment'
where vector.search(VectorFromAttachment, $queryVector)")
.AddParameter("queryVector", new float[] { 0.1f, 0.2f, 0.3f, 0.4f })
.WaitForNonStaleResults()
.ToListAsync();
from index "Companies/ByVector/FromNumericalAttachment"
where vector.search(VectorFromAttachment, $queryVector)
{ "queryVector" : [0.1, 0.2, 0.3, 0.4] }
JS index
-
The following is the JavaScript index format equivalent to the LINQ index shown above.
-
The main difference is that JavaScript indexes do Not support
getContentAsStream()
on attachment objects:- Because of this, embedding vectors must be stored in attachments as Base64-encoded strings.
- Use
getContentAsString()
to retrieve the attachment content as a string, as shown in this example.
public class Companies_ByVector_FromNumericalAttachment_JS :
AbstractJavaScriptIndexCreationTask
{
public Companies_ByVector_FromNumericalAttachment_JS()
{
Maps = new HashSet<string>()
{
$@"map('Companies', function (company) {{
var attachment = loadAttachment(company, 'vector_base64.raw');
if (!attachment) return null;
return {{
VectorFromAttachment: createVector(attachment.getContentAsString('utf8'))
}};
}})"
};
Fields = new();
Fields.Add("VectorFromAttachment", new IndexFieldOptions()
{
Vector = new VectorOptions()
{
SourceEmbeddingType = VectorEmbeddingType.Single,
DestinationEmbeddingType = VectorEmbeddingType.Single
}
});
SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
}
}
// These vectors are simple pre-computed embedding vectors with 32-bit floating-point values.
// Note: In a real scenario, embeddings would be generated by a model.
// ==========================================================================================
var v1 = new float[] { 0.1f, 0.2f, 0.3f, 0.4f };
var v2 = new float[] { 0.1f, 0.7f, 0.8f, 0.9f };
var v3 = new float[] { 0.5f, 0.6f, 0.7f, 0.8f };
// Prepare the embedding vectors as a BASE64 string to be stored as attachments:
// =============================================================================
var base64ForV1 = Convert.ToBase64String(MemoryMarshal.Cast<float, byte>(v1));
var base64ForV2 = Convert.ToBase64String(MemoryMarshal.Cast<float, byte>(v2));
var base64ForV3 = Convert.ToBase64String(MemoryMarshal.Cast<float, byte>(v3));
// Convert to byte[] for streaming:
// ================================
var byteArray1 = Encoding.UTF8.GetBytes(base64ForV1);
var byteArray2 = Encoding.UTF8.GetBytes(base64ForV2);
var byteArray3 = Encoding.UTF8.GetBytes(base64ForV3);
using (var session = store.OpenSession())
{
// Load existing Company documents from RavenDB's sample data:
// ===========================================================
var company1 = session.Load<Company>("companies/60-A");
var company2 = session.Load<Company>("companies/61-A");
var company3 = session.Load<Company>("companies/62-A");
// Store the attachments in the documents (using MemoryStream):
// ============================================================
session.Advanced.Attachments.Store(company1, "vector_base64.raw", new MemoryStream(byteArray1));
session.Advanced.Attachments.Store(company2, "vector_base64.raw", new MemoryStream(byteArray2));
session.Advanced.Attachments.Store(company3, "vector_base64.raw", new MemoryStream(byteArray3));
session.SaveChanges();
}
Execute a vector search using the index:
Results will include Company documents whose attachment contains vectors similar to the query vector.
var similarCompanies = session.Advanced
.RawQuery<Company>(@"
from index 'Companies/ByVector/FromNumericalAttachment/JS'
where vector.search(VectorFromAttachment, $queryVector)")
.AddParameter("queryVector", new float[] { 0.1f, 0.2f, 0.3f, 0.4f })
.WaitForNonStaleResults()
.ToList();
var similarCompanies = await asyncSession.Advanced
.AsyncRawQuery<Company>(@"
from index 'Companies/ByVector/FromNumericalAttachment/JS'
where vector.search(VectorFromAttachment, $queryVector)")
.AddParameter("queryVector", new float[] { 0.1f, 0.2f, 0.3f, 0.4f })
.WaitForNonStaleResults()
.ToListAsync();
from index "Companies/ByVector/FromNumericalAttachment/JS"
where vector.search(VectorFromAttachment, $queryVector)
{ "queryVector" : [0.1, 0.2, 0.3, 0.4] }
Indexing ALL attachments
-
The following index defines a vector field named
VectorFromAttachment
. -
It indexes embeddings generated from the numerical data stored in ALL attachments of all Company documents.
public class Companies_ByVector_AllAttachments :
AbstractIndexCreationTask<Company, Companies_ByVector_AllAttachments.IndexEntry>
{
public class IndexEntry()
{
// This index-field will hold embeddings
// generated from the NUMERICAL content of ALL attachments.
public object VectorFromAttachment { get; set; }
}
public Companies_ByVector_AllAttachments()
{
Map = companies => from company in companies
// Load ALL attachments from the document
let attachments = LoadAttachments(company)
select new IndexEntry
{
// Index the attachments content in the vector field
VectorFromAttachment = CreateVector(
attachments.Select(e => e.GetContentAsStream()))
};
// Configure the vector field:
VectorIndexes.Add(x => x.VectorFromAttachment,
new VectorOptions()
{
SourceEmbeddingType = VectorEmbeddingType.Single,
DestinationEmbeddingType = VectorEmbeddingType.Single
});
SearchEngineType = Raven.Client.Documents.Indexes.SearchEngineType.Corax;
}
}
var indexDefinition = new IndexDefinition
{
Name = "Companies/ByVector/AllAttachments",
Maps = new HashSet<string>
{
@"from company in docs.Companies
let attachments = LoadAttachments(company)
select new
{
VectorFromAttachment =
CreateVector(attachments.Select(e => e.GetContentAsStream()))
}"
},
Fields = new Dictionary<string, IndexFieldOptions>()
{
{
"VectorFromAttachment",
new IndexFieldOptions()
{
Vector = new VectorOptions()
{
SourceEmbeddingType = VectorEmbeddingType.Single,
DestinationEmbeddingType = VectorEmbeddingType.Single,
}
}
}
},
Configuration = new IndexConfiguration()
{
["Indexing.Static.SearchEngineType"] = "Corax"
}
};
store.Maintenance.Send(new PutIndexesOperation(indexDefinition));
// These vectors are simple pre-computed embedding vectors with 32-bit floating-point values.
// Note: In a real scenario, embeddings would be generated by a model.
// ==========================================================================================
var v1 = new float[] { 0.1f, 0.2f, 0.3f, 0.4f };
var v2 = new float[] { 0.5f, 0.6f, 0.7f, 0.8f };
var v3 = new float[] { -0.1f, 0.2f, -0.7f, -0.8f };
var v4 = new float[] { 0.3f, -0.6f, 0.9f, -0.9f };
// Prepare the embedding vectors as `byte[]` to be stored as attachments:
// =====================================================================
var byteArray1 = MemoryMarshal.Cast<float, byte>(v1).ToArray();
var byteArray2 = MemoryMarshal.Cast<float, byte>(v2).ToArray();
var byteArray3 = MemoryMarshal.Cast<float, byte>(v3).ToArray();
var byteArray4 = MemoryMarshal.Cast<float, byte>(v4).ToArray();
using (var session = store.OpenSession())
{
// Load existing Company documents from RavenDB's sample data:
// ===========================================================
var company1 = session.Load<Company>("companies/70-A");
var company2 = session.Load<Company>("companies/71-A");
// Store multiple attachments in the documents (using MemoryStream):
// =================================================================
session.Advanced.Attachments.Store(company1, "vector1.raw", new MemoryStream(byteArray1));
session.Advanced.Attachments.Store(company1, "vector2.raw", new MemoryStream(byteArray2));
session.Advanced.Attachments.Store(company2, "vector1.raw", new MemoryStream(byteArray3));
session.Advanced.Attachments.Store(company2, "vector2.raw", new MemoryStream(byteArray4));
session.SaveChanges();
}
Execute a vector search using the index:
Results will include Company documents whose attachments contains vectors similar to the query vector.
var similarCompanies = session
.Query<Companies_ByVector_AllAttachments.IndexEntry,
Companies_ByVector_AllAttachments>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { -0.1f, 0.2f, -0.7f, -0.8f }))
.Customize(x => x.WaitForNonStaleResults())
.OfType<Company>()
.ToList();
var similarCompanies = await asyncSession
.Query<Companies_ByVector_AllAttachments.IndexEntry,
Companies_ByVector_AllAttachments>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { -0.1f, 0.2f, -0.7f, -0.8f }))
.Customize(x => x.WaitForNonStaleResults())
.OfType<Company>()
.ToListAsync();
var similarCompanies = session.Advanced
.DocumentQuery<Companies_ByVector_AllAttachments.IndexEntry,
Companies_ByVector_AllAttachments>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { -0.1f, 0.2f, -0.7f, -0.8f }))
.WaitForNonStaleResults()
.OfType<Company>()
.ToList();
var similarCompanies = await asyncSession.Advanced
.AsyncDocumentQuery<Companies_ByVector_AllAttachments.IndexEntry,
Companies_ByVector_AllAttachments>()
.VectorSearch(
field => field
.WithField(x => x.VectorFromAttachment),
queryVector => queryVector
.ByEmbedding(new float[] { -0.1f, 0.2f, -0.7f, -0.8f }))
.WaitForNonStaleResults()
.OfType<Company>()
.ToListAsync();
var similarCompanies = session.Advanced
.RawQuery<Company>(@"
from index 'Companies/ByVector/AllAttachments'
where vector.search(VectorFromAttachment, $queryVector)")
.AddParameter("queryVector", new float[] { 0.1f, 0.2f, -0.7f, -0.8f })
.WaitForNonStaleResults()
.ToList();
var similarCompanies = await asyncSession.Advanced
.AsyncRawQuery<Company>(@"
from index 'Companies/ByVector/AllAttachments'
where vector.search(VectorFromAttachment, $queryVector)")
.AddParameter("queryVector", new float[] { 0.1f, 0.2f, -0.7f, -0.8f })
.WaitForNonStaleResults()
.ToListAsync();
from index "Companies/ByVector/AllAttachments"
where vector.search(VectorFromAttachment, $queryVector)
{ "queryVector" : [0.1, 0.2, -0.7, -0.8] }