Sdílet prostřednictvím


Full-Text Hledání ve poskytovateli EF Core SQL Serveru

SQL Server poskytuje funkce fulltextového vyhledávání , které umožňují sofistikované vyhledávání textu nad rámec jednoduchých LIKE vzorů. Fulltextové vyhledávání podporuje lingvistické porovnávání, inflexní formuláře, vyhledávání bezkontaktní komunikace a vážené hodnocení.

Poskytovatel SQL Serveru EF Core podporuje predikáty fulltextového vyhledávání (pro filtrování) i funkce hodnotné tabulkou (pro filtrování pomocí řazení).

Před použitím fulltextového vyhledávání musíte ve své databázi vytvořit fulltextový katalog a fulltextový index sloupců, které chcete prohledat.

Poznámka:

Fulltextový katalog a správa indexů při migracích byla zavedena v EF Core 11.

Fulltextové katalogy a indexy můžete nakonfigurovat přímo v modelu EF. Když přidáte migraci, EF vygeneruje příslušný SQL pro vytvoření (nebo změnu) katalogu a indexu za vás.

Nejprve definujte fulltextový katalog modelu a pak nakonfigurujte fulltextový index pro typ entity:

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

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

Metoda HasKeyIndex() určuje jedinečný index s jedním sloupcem, který není null, který se používá jako fulltextový klíč tabulky (obvykle index primárního klíče). OnCatalog() přiřadí fulltextový index ke konkrétnímu katalogu.

Můžete také nakonfigurovat více sloupců a další možnosti, jako jsou jazyky pro jednotlivé sloupce a sledování změn:

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

Fulltextový katalog lze také nakonfigurovat jako výchozí katalog a s citlivostí na přízvuky.

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

Další informace najdete v dokumentaci k fulltextovém vyhledávání SQL Serveru.

Fulltextové predikáty

EF Core podporuje FREETEXT() a CONTAINS() predikáty, které se používají v Where() klauzulích k filtrování výsledků.

FREETEXT()

FREETEXT() provádí méně striktní porovnávání, vyhledávání slov na základě jejich významu, včetně inflexních formulářů (například slovesných časů a podstatných jmen v množném čísle):

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

To se překládá na:

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

Volitelně můžete zadat jazykový termín:

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

CONTAINS()

CONTAINS() provádí přesnější porovnávání a podporuje sofistikovanější kritéria hledání, včetně předponových termínů, vyhledávání podle blízkosti a vážených termínů.

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

To se překládá na:

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

Další informace o CONTAINS() syntaxi dotazů najdete v dokumentaci k SQL Serveru CONTAINS.

Fulltextové tabulkové funkce

Poznámka:

Funkce s fulltextovou hodnotou tabulky se zavádějí v EF Core 11.

I když výše uvedené predikáty jsou užitečné pro filtrování, neposkytují informace o řazení. Funkce SQL Serveru vracející tabulky FREETEXTTABLE() a CONTAINSTABLE() vracejí jak odpovídající řádky, tak i skóre hodnocení, které určuje, jak dobře jednotlivé řádky odpovídají vyhledávacímu dotazu.

FreeTextTable()

FreeTextTable() je verze FreeText()funkce s hodnotou tabulky . Vrátí FullTextSearchResult<TEntity>, která zahrnuje entitu i hodnotu řazení:

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

Všimněte si, že je nutné zadat parametry obecného typu; Article odpovídá prohledávanému typu entity, kde int je klíč fulltextového vyhledávání zadaný při vytváření indexu a který je vrácen .FREETEXTTABLE()

Výše uvedené automaticky prohledává všechny sloupce registrované pro fulltextové vyhledávání a zobrazí 10 nejlepších shod. Můžete také zadat konkrétní sloupec, který se má prohledávat:

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

... nebo více sloupců:

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() je verze Contains()funkce s hodnotou tabulky , která podporuje stejnou sofistikovanou syntaxi vyhledávání a zároveň poskytuje informace o řazení:

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

Omezení výsledků

Obě funkce s hodnotami tabulky podporují topN parametr pro omezení počtu výsledků:

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

Určení jazyka

Obě funkce hodnotné tabulkou podporují zadání jazykového termínu pro lingvistické porovnávání:

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

Kdy použít predikáty versus tabulkově hodnotné funkce

funkce Predikáty (FreeText(), Contains()) Tabulkové funkce (FreeTextTable(), ContainsTable())
Poskytuje pořadí. ❌ Ne ✅ Ano
Výkon pro velké sady výsledků Lepší pro filtrování Lepší pro hodnocení a řazení
Kombinování s jinými entitami Spojení prostřednictvím spojení Předdefinovaný výsledek entity
Použití v Where() klauzuli ✅ Ano ❌ Ne (použít jako zdroj)

Predikáty použijte, když jednoduše potřebujete filtrovat výsledky na základě kritérií fulltextového vyhledávání. Použijte tabulkové funkce, když potřebujete informace o řazení výsledků podle relevance nebo zobrazení jejich skóre relevance uživatelům.