A common requirement in modern applications is implementing full-text search.
Full-Text search allows you to efficiently search text content and evaluate the relevance of documents to a given search query.
It goes beyond simple equality or LIKE searches by using advanced text processing techniques such as tokenization, stemming and stop word removal.
Additionally, full-text search provides relevance scoring, helping rank documents based on how well they match a query.
Cosmos DB uses Best Matching 25 (BM25), which considers factors like term frequency, inverse document frequency and document length to compute relevance scores.
With EF Core 10, you can now model your entities with full-text search-enabled properties and use full-text search functions directly in LINQ queries targeting Azure Cosmos DB.
Full-text search can also be combined with vector search for hybrid search scenarios. For more details, see my blog post on Hybrid Search.
Entity Configuration
First, install the required NuGet package:
Install-Package Microsoft.EntityFrameworkCore.Cosmos
Then configure your entity to enable full-text search:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Document>(entity =>
{
entity.ToContainer("MyDocs");
entity.Property(x => x.Id)
.ToJsonProperty("Id");
entity.HasPartitionKey("Id");
entity.Property(x => x.Content).EnableFullTextSearch();
entity.HasIndex(x => x.Content).IsFullTextIndex();
});
}
This configuration now enables full-text search on the Content property.
NOTE: Ensure your Cosmos DB container has a full-text policy and full-text index configured. While queries can run without them, they won’t leverage the index efficiently, which can increase request units (RUs) and query execution time.
While it's possible to run full-text search queries without these policies, they won't utilize the full-text index and can consume higher request units and have longer execution times.
Full-text policy example:
{
"defaultLanguage": "en-US",
"fullTextPaths": [
{
"path": "/text",
"language": "en-US"
}
]
}
Full-text index example:
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/*"
}
],
"excludedPaths": [
{
"path": "/"_etag"/?"
},
],
"fullTextIndexes": [
{
"path": "/text"
}
]
}
Azure Cosmos DB Setup
Register your DbContext and configure the connection:
builder.Services.AddDbContextPool<ApplicationDbContext>(options =>
{
options.UseCosmos(
builder.Configuration.GetConnectionString("CosmosDb"),
builder.Configuration["CosmosDb:DatabaseName"]);
});
Add the Cosmos DB connection details to your appsettings.json:
{
"ConnectionStrings": {
"CosmosDb": "AccountEndpoint=https://<your-account>.documents.azure.com:443/;AccountKey=<your-key>"
},
"CosmosDb": {
"DatabaseName": "<your-database-name>"
}
}
Text Search
You can now perform full-text search directly in LINQ. EF Core translates it to Cosmos DB's native search capabilities:
app.MapGet("/api/documents/full-text-search", async (string query, ApplicationDbContext db) =>
{
var keywords = query.Split(' ', StringSplitOptions.RemoveEmptyEntries);
var results = await db.Documents
.OrderBy(x => EF.Functions.FullTextScore(x.Content, keywords))
.Take(20)
.AsNoTracking()
.ToListAsync();
return Results.Ok(results);
});
Supported full-text operations:
Conclusion
Full-text search in EF Core 10 combined with Azure Cosmos DB offers a powerful and efficient way to implement advanced text search in modern applications.
With built-in relevance scoring and full-text indexing, you can deliver accurate search results while optimizing performance and resource usage.
When paired with vector search, it makes a versatile solution for applications that require both keyword and semantic search capabilities.
If you want to check out examples I created, you can find the source code here:
Source CodeI hope you enjoyed it, subscribe and get a notification when a new blog is up!
