Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O SQL Server fornece recursos de pesquisa de texto completo que permitem uma pesquisa de texto sofisticada além de padrões simples LIKE . A pesquisa de texto completo dá suporte à correspondência linguística, formas flexionais, pesquisa por proximidade e classificação ponderada.
O provedor do SQL Server do EF Core dá suporte a predicados de pesquisa de texto completo (para filtragem) e funções com valor de tabela (para filtragem com classificação).
Configurando a pesquisa de texto completo
Antes de usar a pesquisa de texto completo, você deve criar um catálogo de texto completo em seu banco de dados e um índice de texto completo nas colunas que deseja pesquisar.
Observação
O catálogo de texto completo e o gerenciamento de índice nas migrações foram introduzidos no EF Core 11.
Você pode configurar catálogos de texto completo e índices diretamente em seu modelo EF. Quando você adiciona uma migração, o EF gerará o código SQL apropriado para criar ou alterar o catálogo e o índice para você.
Primeiro, defina um catálogo de texto completo no modelo e configure um índice de texto completo no tipo de entidade:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasFullTextCatalog("ftCatalog");
modelBuilder.Entity<Article>()
.HasFullTextIndex(a => a.Contents)
.HasKeyIndex("PK_Articles")
.OnCatalog("ftCatalog");
}
O HasKeyIndex() método especifica o índice de coluna única exclusivo, não anulável, usado como a chave de texto completo para a tabela (normalmente o índice de chave primária).
OnCatalog() atribui o índice de texto completo a um catálogo específico.
Você também pode configurar várias colunas e opções adicionais, como idiomas por coluna e controle de alterações:
modelBuilder.Entity<Article>()
.HasFullTextIndex(a => new { a.Title, a.Contents })
.HasKeyIndex("PK_Articles")
.OnCatalog("ftCatalog")
.WithChangeTracking(FullTextChangeTracking.Manual)
.HasLanguage("Title", "English")
.HasLanguage("Contents", "French");
O catálogo de texto completo também pode ser configurado como o catálogo padrão e com sensibilidade a acentos.
modelBuilder.HasFullTextCatalog("ftCatalog")
.IsDefault()
.IsAccentSensitive(false);
Para obter mais informações, consulte a documentação de pesquisa de texto completo do SQL Server.
Predicados de texto completo
O EF Core dá suporte aos predicados FREETEXT() e CONTAINS(), que são usados em cláusulas Where() para filtrar resultados.
FREETEXT()
FREETEXT() executa uma correspondência menos estrita, procurando palavras com base em seu significado, incluindo formas flexionais (como tempos de verbo e plurais de substantivos):
var articles = await context.Articles
.Where(a => EF.Functions.FreeText(a.Contents, "veggies"))
.ToListAsync();
Isto traduz-se em:
SELECT [a].[Id], [a].[Title], [a].[Contents]
FROM [Articles] AS [a]
WHERE FREETEXT([a].[Contents], N'veggies')
Opcionalmente, você pode especificar um termo de idioma:
var articles = await context.Articles
.Where(a => EF.Functions.FreeText(a.Contents, "veggies", "English"))
.ToListAsync();
CONTAINS()
CONTAINS() executa correspondências mais precisas e dá suporte a critérios de pesquisa mais sofisticados, incluindo termos de prefixo, pesquisa de proximidade e termos ponderados:
// Simple search
var articles = await context.Articles
.Where(a => EF.Functions.Contains(a.Contents, "veggies"))
.ToListAsync();
// Prefix search (words starting with "vegg")
var articles = await context.Articles
.Where(a => EF.Functions.Contains(a.Contents, "\"vegg*\""))
.ToListAsync();
// Phrase search
var articles = await context.Articles
.Where(a => EF.Functions.Contains(a.Contents, "\"fresh vegetables\""))
.ToListAsync();
Isto traduz-se em:
SELECT [a].[Id], [a].[Title], [a].[Contents]
FROM [Articles] AS [a]
WHERE CONTAINS([a].[Contents], N'veggies')
Para obter mais informações sobre CONTAINS() a sintaxe da consulta, consulte a documentação do SQL Server CONTAINS.
Funções com valor de tabela de texto completo
Observação
Funções com valor de tabela de texto completo estão sendo introduzidas no EF Core 11.
Embora os predicados acima sejam úteis para filtragem, eles não fornecem informações de classificação. As funções FREETEXTTABLE() com valor de tabela do SQL Server e CONTAINSTABLE() retornam ambas as linhas correspondentes e uma pontuação de classificação que indica o quão bem cada linha corresponde à consulta de pesquisa.
FreeTextTable()
FreeTextTable() é a versão da função com valor de tabela de FreeText(). Retorna FullTextSearchResult<TEntity>, que inclui a entidade e o valor da classificação:
var results = await context.Articles
.Join(
context.Articles.FreeTextTable<Article, int>("veggies", topN: 10),
a => a.Id,
ftt => ftt.Key,
(a, ftt) => new { Article = a, ftt.Rank })
.OrderByDescending(r => r.Rank)
.ToListAsync();
foreach (var result in results)
{
Console.WriteLine($"Article {result.Article.Id} with rank {result.Rank}");
}
Observe que você deve fornecer os parâmetros de tipo genérico; Article corresponde ao tipo de entidade que está sendo pesquisado, onde int está a chave de pesquisa de texto completo especificada ao criar o índice e que é retornada por FREETEXTTABLE().
A ação acima pesquisa automaticamente em todas as colunas registradas para pesquisa de texto completo e retorna as principais 10 correspondências. Você também pode fornecer uma coluna específica para pesquisar:
var results = await context.Articles
.Join(
context.Articles.FreeTextTable<Article, int>(a => a.Contents, "veggies"),
a => a.Id,
ftt => ftt.Key,
(a, ftt) => new { Article = a, ftt.Rank })
.OrderByDescending(r => r.Rank)
.ToListAsync();
... ou várias colunas:
var results = await context.Articles
.FreeTextTable(a => new { a.Title, a.Contents }, "veggies")
.Select(r => new { Article = r.Value, Rank = r.Rank })
.OrderByDescending(r => r.Rank)
.ToListAsync();
ContainsTable()
ContainsTable() é a versão da função com valor de tabela de Contains(), dando suporte à mesma sintaxe de pesquisa sofisticada, ao mesmo tempo em que fornece informações de classificação:
var results = await context.Articles
.Join(
context.Articles.ContainsTable<Article, int>( "veggies OR fruits"),
a => a.Id,
ftt => ftt.Key,
(a, ftt) => new { Article = a, ftt.Rank })
.OrderByDescending(r => r.Rank)
.ToListAsync();
Limitando resultados
Ambas as funções com valor de tabela dão suporte a um topN parâmetro para limitar o número de resultados:
var results = await context.Articles
.FreeTextTable(a => a.Contents, "veggies", topN: 10)
.Select(r => new { Article = r.Value, Rank = r.Rank })
.OrderByDescending(r => r.Rank)
.ToListAsync();
Especificando um idioma
Ambas as funções com valor de tabela dão suporte à especificação de um termo de idioma para correspondência linguística:
var results = await context.Articles
.FreeTextTable(a => a.Contents, "veggies", languageTerm: "English")
.Select(r => new { Article = r.Value, Rank = r.Rank })
.ToListAsync();
Quando usar predicados versus funções com valor de tabela
| Característica | Predicados (FreeText(), Contains()) |
Funções com valor de tabela (FreeTextTable(), ContainsTable()) |
|---|---|---|
| Fornece classificação | ❌ Não | ✅ Sim |
| Desempenho para conjuntos de resultados grandes | Melhor para filtragem | Melhor para ranqueamento e classificação |
| Combinar com outras entidades | Por meio de junções | Resultado da entidade integrada |
Usar na Where() cláusula |
✅ Sim | ❌ Não (usar como origem) |
Use predicados quando você simplesmente precisar filtrar resultados com base nos critérios de pesquisa de texto completo. Use funções com valor de tabela quando precisar de informações de classificação para ordenar resultados por relevância ou exibir pontuações de relevância para os usuários.