Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
44 changes: 30 additions & 14 deletions entity-framework/core/providers/sql-server/vector-search.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ Once you have a vector index, use the `VectorSearch()` extension method on your

```csharp
var blogs = await context.Blogs
.VectorSearch(b => b.Embedding, embedding, "cosine", topN: 5)
.VectorSearch(b => b.Embedding, embedding, "cosine")
.OrderBy(r => r.Distance)
.Take(5)
.ToListAsync();

foreach (var (blog, score) in blogs)
Expand All @@ -141,18 +143,26 @@ foreach (var (blog, score) in blogs)
This translates to the following SQL:

```sql
SELECT [v].[Id], [v].[Name], [v].[Distance]
FROM VECTOR_SEARCH([Blogs], 'Embedding', @__embedding, 'metric = cosine', @__topN)
SELECT TOP(@p) WITH APPROXIMATE [b].[Id], [b].[Name], [v].[Distance]
FROM VECTOR_SEARCH(
TABLE = [Blogs] AS [b],
COLUMN = [Embedding],
SIMILAR_TO = @p1,
METRIC = 'cosine'
) AS [v]
ORDER BY [v].[Distance]
```

The `topN` parameter specifies the maximum number of results to return.
Compose `VectorSearch()` with `OrderBy(r => r.Distance)` and `Take(...)` to limit the number of results returned as required for approximate vector search.

`VectorSearch()` returns `VectorSearchResult<TEntity>`, which allows you to access both the entity and the computed distance:

```csharp
var searchResults = await context.Blogs
.VectorSearch(b => b.Embedding, embedding, "cosine", topN: 5)
.VectorSearch(b => b.Embedding, embedding, "cosine")
.Where(r => r.Distance < 0.05)
.OrderBy(r => r.Distance)
.Take(5)
.Select(r => new { Blog = r.Value, Distance = r.Distance })
.ToListAsync();
```
Expand All @@ -175,7 +185,10 @@ var results = await context.Articles
.FreeTextTable<Article, int>(textualQuery, topN: k)
// Perform vector (semantic) search, joining the results of both searches together
.LeftJoin(
context.Articles.VectorSearch(b => b.Embedding, queryEmbedding, "cosine", topN: k),
context.Articles
.VectorSearch(b => b.Embedding, queryEmbedding, "cosine")
.OrderBy(r => r.Distance)
.Take(k),
fts => fts.Key,
vs => vs.Value.Id,
(fts, vs) => new
Expand Down Expand Up @@ -211,12 +224,15 @@ The query produces the following SQL:
```sql
SELECT TOP(@p3) [a0].[Id], [a0].[Content], [a0].[Title]
FROM FREETEXTTABLE([Articles], *, @p, @p1) AS [f]
LEFT JOIN VECTOR_SEARCH(
TABLE = [Articles] AS [a0],
COLUMN = [Embedding],
SIMILAR_TO = @p2,
METRIC = 'cosine',
TOP_N = @p3
) AS [v] ON [f].[KEY] = [a0].[Id]
ORDER BY 1.0E0 / CAST(10 + [f].[RANK] AS float) + ISNULL(1.0E0 / (10.0E0 + [v].[Distance]), 0.0E0) DESC
LEFT JOIN (
SELECT TOP(@p4) WITH APPROXIMATE [a0].[Id], [a0].[Content], [a0].[Title], [v].[Distance]
FROM VECTOR_SEARCH(
TABLE = [Articles] AS [a0],
COLUMN = [Embedding],
SIMILAR_TO = @p2,
METRIC = 'cosine'
) AS [v]
ORDER BY [v].[Distance]
) AS [v0] ON [f].[KEY] = [v0].[Id]
ORDER BY 1.0E0 / CAST(10 + [f].[RANK] AS float) + ISNULL(1.0E0 / (10.0E0 + [v0].[Distance]), 0.0E0) DESC
```
6 changes: 4 additions & 2 deletions entity-framework/core/what-is-new/ef-core-11.0/whatsnew.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,13 @@ Once you have a vector index, you can use the `VectorSearch()` extension method

```csharp
var blogs = await context.Blogs
.VectorSearch(b => b.Embedding, embedding, "cosine", topN: 5)
.VectorSearch(b => b.Embedding, embedding, "cosine")
.OrderBy(r => r.Distance)
.Take(5)
.ToListAsync();
```

This translates to the SQL Server [`VECTOR_SEARCH()`](/sql/t-sql/functions/vector-search-transact-sql) table-valued function, which performs an approximate search over the vector index. The `topN` parameter specifies the number of results to return.
This translates to the SQL Server [`VECTOR_SEARCH()`](/sql/t-sql/functions/vector-search-transact-sql) table-valued function, which performs an approximate search over the vector index. Compose with `OrderBy(r => r.Distance)` and `Take(...)` to limit the number of results returned.

`VectorSearch()` returns `VectorSearchResult<TEntity>`, allowing you to access the distance alongside the entity.

Expand Down