Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
SQL Server fournit des fonctionnalités de recherche en texte intégral qui permettent une recherche de texte sophistiquée au-delà de modèles simples LIKE . La recherche en texte intégral prend en charge la correspondance linguistique, les formulaires inlectionnels, la recherche de proximité et le classement pondéré.
Le fournisseur SQL Server d’EF Core prend en charge les prédicats de recherche en texte intégral (pour le filtrage) et les fonctions à valeurs de table (pour le filtrage avec classement).
Configuration de la recherche en texte intégral
Avant d’utiliser la recherche en texte intégral, vous devez créer un catalogue de texte intégral sur votre base de données et un index de recherche en texte intégral sur les colonnes que vous souhaitez rechercher.
Note
Le catalogue de texte intégral et la gestion des index dans les migrations ont été introduits dans EF Core 11.
Vous pouvez configurer des catalogues de texte intégral et des index directement dans votre modèle EF. Lorsque vous ajoutez une migration, EF génèrera le SQL approprié afin de créer ou de modifier le catalogue et l'index pour vous.
Tout d’abord, définissez un catalogue de texte intégral sur le modèle, puis configurez un index de recherche en texte intégral sur votre type d’entité :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasFullTextCatalog("ftCatalog");
modelBuilder.Entity<Article>()
.HasFullTextIndex(a => a.Contents)
.HasKeyIndex("PK_Articles")
.OnCatalog("ftCatalog");
}
La HasKeyIndex() méthode spécifie l’index unique, non nullable et à colonne unique utilisé comme clé de texte intégral pour la table (généralement l’index de clé primaire).
OnCatalog() affecte l’index de recherche en texte intégral à un catalogue spécifique.
Vous pouvez également configurer plusieurs colonnes et des options supplémentaires telles que les langues par colonne et le suivi des modifications :
modelBuilder.Entity<Article>()
.HasFullTextIndex(a => new { a.Title, a.Contents })
.HasKeyIndex("PK_Articles")
.OnCatalog("ftCatalog")
.WithChangeTracking(FullTextChangeTracking.Manual)
.HasLanguage("Title", "English")
.HasLanguage("Contents", "French");
Le catalogue de texte intégral peut également être configuré en tant que catalogue par défaut et avec sensibilité aux accents.
modelBuilder.HasFullTextCatalog("ftCatalog")
.IsDefault()
.IsAccentSensitive(false);
Pour plus d’informations, consultez la documentation de recherche en texte intégral SQL Server.
Prédicats de texte intégral
EF Core prend en charge les prédicats FREETEXT() et CONTAINS(), qui sont utilisés dans les clauses Where() pour filtrer les résultats.
FREETEXT()
FREETEXT() effectue une correspondance moins stricte, en recherchant des mots basés sur leur signification, y compris les formes inflectionnelles (telles que les temps de verbes et les pluriels nominaux) :
var articles = await context.Articles
.Where(a => EF.Functions.FreeText(a.Contents, "veggies"))
.ToListAsync();
Cela se traduit par :
SELECT [a].[Id], [a].[Title], [a].[Contents]
FROM [Articles] AS [a]
WHERE FREETEXT([a].[Contents], N'veggies')
Vous pouvez éventuellement spécifier un terme de langue :
var articles = await context.Articles
.Where(a => EF.Functions.FreeText(a.Contents, "veggies", "English"))
.ToListAsync();
CONTAINS()
CONTAINS() effectue une correspondance plus précise et prend en charge des critères de recherche plus sophistiqués, notamment les termes de préfixe, la recherche de proximité et les termes pondérés :
// 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();
Cela se traduit par :
SELECT [a].[Id], [a].[Title], [a].[Contents]
FROM [Articles] AS [a]
WHERE CONTAINS([a].[Contents], N'veggies')
Pour plus d’informations sur CONTAINS() la syntaxe des requêtes, consultez la documentation de la SQL Server CONTAINS.
Fonctions avec valeur de table de texte intégral
Note
Les fonctions table évaluées sur texte intégral sont introduites dans EF Core 11.
Bien que les prédicats ci-dessus soient utiles pour le filtrage, ils ne fournissent pas d’informations de classement. Les fonctions table de SQL Server, FREETEXTTABLE() et CONTAINSTABLE(), retournent à la fois les lignes correspondantes et un score de classement qui indique le niveau de correspondance de chaque ligne avec la requête de recherche.
FreeTextTable()
FreeTextTable() est la version de la fonction à valeur de table de FreeText(). Elle retourne FullTextSearchResult<TEntity>, qui inclut à la fois l’entité et la valeur de classement :
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}");
}
Notez que vous devez fournir les paramètres de type générique ; Article correspond au type d’entité en cours de recherche, où int est la clé de recherche en texte intégral spécifiée lors de la création de l’index, et qui est retournée par FREETEXTTABLE().
Ce qui précède recherche automatiquement toutes les colonnes enregistrées pour la recherche en texte intégral et retourne les 10 premières correspondances. Vous pouvez également fournir une colonne spécifique à rechercher :
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 plusieurs colonnes :
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() est la version de la fonction table de Contains(), prenant en charge la même syntaxe de recherche sophistiquée tout en fournissant des informations de classement :
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();
Limitation des résultats
Les deux fonctions de valeur de table prennent en charge un paramètre topN pour limiter le nombre de résultats :
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();
Spécification d’une langue
Les deux fonctions de type table prennent en charge la spécification d’un terme de langue pour la correspondance linguistique :
var results = await context.Articles
.FreeTextTable(a => a.Contents, "veggies", languageTerm: "English")
.Select(r => new { Article = r.Value, Rank = r.Rank })
.ToListAsync();
Quand utiliser des prédicats ou des fonctions à valeurs de table
| Fonctionnalité | Prédicats (FreeText(), Contains()) |
Fonctions à valeurs de table (FreeTextTable(), ContainsTable()) |
|---|---|---|
| Fournit le classement | ❌ Non | ✅ Oui |
| Performance pour les ensembles de résultats volumineux | Mieux pour le filtrage | Mieux pour le classement et le tri |
| Combiner avec d’autres entités | Par l'intermédiaire de jointures | Résultat de l’entité intégrée |
Utiliser dans la clause Where() |
✅ Oui | ❌ Non (utiliser comme source) |
Utilisez des prédicats lorsque vous devez simplement filtrer les résultats en fonction des critères de recherche en texte intégral. Utilisez des fonctions évaluées en table lorsque vous avez besoin d'informations de classement afin de classer les résultats en fonction de leur pertinence ou d'afficher des scores de pertinence aux utilisateurs.