Megosztás a következőn keresztül:


Full-Text Keresés az SQL Server EF Core-szolgáltatójában

Az SQL Server teljes szöveges keresési képességeket biztosít, amelyek egyszerű mintákon túl LIKE kifinomult szövegkeresést tesznek lehetővé. A teljes szöveges keresés támogatja a nyelvi egyeztetést, az inflekciós formákat, a közelségi keresést és a súlyozott rangsorolást.

Az EF Core SQL Server-szolgáltatója támogatja a teljes szöveges keresési predikátumokat (szűréshez) és a táblaértékű függvényeket (a rangsorolással történő szűréshez).

A teljes szöveges keresés előtt létre kell hoznia egy teljes szöveges katalógust az adatbázison, és egy teljes szöveges indexet kell létrehoznia a keresendő oszlopokon.

Megjegyzés:

A teljes szöveges katalógus és az indexkezelés a migrálásokban az EF Core 11-ben lett bevezetve.

A teljes szöveges katalógusokat és indexeket közvetlenül az EF-modellben konfigurálhatja. Migrálás hozzáadásakor az EF létrehozza a megfelelő SQL-t a katalógus és az index létrehozásához (vagy módosításához).

Először definiáljon egy teljes szöveges katalógust a modellen, majd konfiguráljon egy teljes szöveges indexet az entitástípuson:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasFullTextCatalog("ftCatalog");

    modelBuilder.Entity<Article>()
        .HasFullTextIndex(a => a.Contents)
        .HasKeyIndex("PK_Articles")
        .OnCatalog("ftCatalog");
}

A HasKeyIndex() metódus a táblázat teljes szöveges kulcsaként (általában az elsődleges kulcsindex) használt egyedi, nem null értékű, egyoszlopos indexet adja meg. OnCatalog() a teljes szöveges indexet egy adott katalógushoz rendeli.

Több oszlopot és további beállításokat is konfigurálhat, például oszloponkénti nyelveket és változáskövetést:

modelBuilder.Entity<Article>()
    .HasFullTextIndex(a => new { a.Title, a.Contents })
    .HasKeyIndex("PK_Articles")
    .OnCatalog("ftCatalog")
    .WithChangeTracking(FullTextChangeTracking.Manual)
    .HasLanguage("Title", "English")
    .HasLanguage("Contents", "French");

A teljes szöveges katalógus is konfigurálható alapértelmezett katalógusként, ékezetes érzékenység mellett:

modelBuilder.HasFullTextCatalog("ftCatalog")
    .IsDefault()
    .IsAccentSensitive(false);

További információkért tekintse meg az SQL Server teljes szöveges keresési dokumentációját.

Teljes szöveges predikátumok

Az EF Core támogatja a FREETEXT() és CONTAINS() predikátumokat, amelyeket Where() záradékokban használnak az eredmények szűrésére.

SZABADSZÖVEG()

FREETEXT() kevésbé szigorú egyeztetést végez, jelentésük alapján keres szavakat, beleértve az inflekciós formákat (például az igeidőket és a főnévi többes számokat):

var articles = await context.Articles
    .Where(a => EF.Functions.FreeText(a.Contents, "veggies"))
    .ToListAsync();

Ez a következőre fordítható:

SELECT [a].[Id], [a].[Title], [a].[Contents]
FROM [Articles] AS [a]
WHERE FREETEXT([a].[Contents], N'veggies')

Megadhat egy nyelvi kifejezést is:

var articles = await context.Articles
    .Where(a => EF.Functions.FreeText(a.Contents, "veggies", "English"))
    .ToListAsync();

CONTAINS()

CONTAINS() pontosabb egyeztetést végez, és kifinomultabb keresési feltételeket támogat, beleértve az előtagkifejezéseket, a közelségi keresést és a súlyozott kifejezéseket:

// 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();

Ez a következőre fordítható:

SELECT [a].[Id], [a].[Title], [a].[Contents]
FROM [Articles] AS [a]
WHERE CONTAINS([a].[Contents], N'veggies')

A lekérdezési szintaxissal CONTAINS() kapcsolatos további információkért tekintse meg az SQL Server CONTAINS dokumentációját.

Teljes szövegű táblaértékelt függvények

Megjegyzés:

Az EF Core 11-ben bevezetésre kerülnek a teljes szöveges táblázat értékű függvények.

Bár a fenti predikátumok hasznosak a szűréshez, nem nyújtanak rangsorolási információkat. Az SQL Server táblaértékű függvényei FREETEXTTABLE() egyező CONTAINSTABLE() sorokat és rangsorolási pontszámot is ad vissza, amely jelzi, hogy az egyes sorok mennyire egyeznek a keresési lekérdezéssel.

FreeTextTable()

FreeTextTable() a FreeText() táblaértékű függvény verziója. Visszaadja az entitást FullTextSearchResult<TEntity>és a rangsorolási értéket is:

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}");
}

Vegye figyelembe, hogy meg kell adnia az általános típusparamétereket; Article a keresendő entitástípusnak felel meg, ahol int az index létrehozásakor megadott teljes szöveges keresési kulcs található, amelyet a rendszer visszaad FREETEXTTABLE().

A fentiek automatikusan keresnek az összes olyan oszlopban, amely teljes szöveges keresésre van regisztrálva, és a 10 legjobb találatot adja vissza. Egy adott oszlopot is megadhat a kereséshez:

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();

... vagy több oszlop:

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 táblázat értékének függvényverziója Contains(), amely ugyanazt a kifinomult keresési szintaxist támogatja, miközben rangsorolási információkat is biztosít:

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();

Eredmények korlátozása

Mindkét táblaértékű függvény támogat egy paramétert topN az eredmények számának korlátozásához:

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();

Nyelv megadása

Mindkét táblaértékű függvény támogatja a nyelvi megfeleltetés nyelvi kifejezésének megadását:

var results = await context.Articles
    .FreeTextTable(a => a.Contents, "veggies", languageTerm: "English")
    .Select(r => new { Article = r.Value, Rank = r.Rank })
    .ToListAsync();

Mikor érdemes predikátumokat és táblaértékű függvényeket használni?

Funkció Predikátumok (FreeText(), Contains()) Táblaértékű függvények (FreeTextTable(), ContainsTable())
Rangsorolást biztosít ❌ Nem ✅ Igen
Nagy eredményhalmazok teljesítménye Hatékonyabb szűréshez Jobb rangsoroláshoz és rendezéshez
Kombinálás más entitásokkal Illesztéseken keresztül Beépített entitás eredménye
Használat a(z) Where() záradékban ✅ Igen ❌ Nem (forrásként használva)

Akkor használjon predikátumokat, ha egyszerűen csak a teljes szöveges keresési feltételek alapján kell szűrnie a találatokat. Táblaértékű függvényeket akkor használjon, ha rangsorolási információkra van szüksége az eredmények relevancia szerinti sorrendbe helyezéséhez vagy a felhasználók számára a relevanciaértékek megjelenítéséhez.