Condividi tramite


Ricerca a testo completo

Azure Cosmos DB offre ora il supporto per la ricerca full-text. Consente ricerche di testo efficienti ed efficaci usando tecniche avanzate come lo stemming, nonché la valutazione della pertinenza dei documenti in una determinata query di ricerca. Può essere usato in combinazione con la ricerca vettoriale (ad esempio la ricerca ibrida) per migliorare l'accuratezza delle risposte in alcuni scenari di intelligenza artificiale. EF Core consente di modellare il database con proprietà abilitate per la ricerca full-text e di usare funzioni di ricerca full-text all'interno di query destinate ad Azure Cosmos DB.

Configurazione del modello

Una proprietà può essere configurata all'interno OnModelCreating di per usare la ricerca full-text abilitandola per la proprietà e definendo un indice full-text:

public class Blog
{
    ...

    public string Contents { get; set; }
}

public class BloggingContext
{
    ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>(b =>
        {
            b.Property(x => x.Contents).EnableFullTextSearch();
            b.HasIndex(x => x.Contents).IsFullTextIndex();
        });
    }
}

Annotazioni

La configurazione dell'indice non è obbligatoria, ma è consigliabile perché migliora notevolmente le prestazioni delle query di ricerca full-text.

Le operazioni di ricerca full-text sono specifiche della lingua; usano l'inglese americano per impostazione predefinita (en-US). È possibile personalizzare la lingua per le singole proprietà come parte della EnableFullTextSearch chiamata:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>(b =>
        {
            b.Property(x => x.Contents).EnableFullTextSearch();
            b.HasIndex(x => x.Contents).IsFullTextIndex();
            b.Property(x => x.ContentsGerman).EnableFullTextSearch("de-DE");
            b.HasIndex(x => x.ContentsGerman).IsFullTextIndex();
        });
    }

È anche possibile impostare una lingua predefinita per il contenitore, a meno che non venga sottoposto a override nel EnableFullTextSearch metodo , tutte le proprietà full-text all'interno del contenitore useranno tale lingua.

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>(b =>
        {
            b.HasDefaultFullTextLanguage("de-DE");
            b.Property(x => x.ContentsEnglish).EnableFullTextSearch("en-US");
            b.HasIndex(x => x.ContentsEnglish).IsFullTextIndex();
            b.Property(x => x.ContentsGerman).EnableFullTextSearch();
            b.HasIndex(x => x.ContentsGerman).IsFullTextIndex();
            b.Property(x => x.TagsGerman).EnableFullTextSearch();
            b.HasIndex(x => x.TagsGerman).IsFullTextIndex();
        });
    }

Query

Nell'ambito della funzionalità di ricerca full-text, Azure Cosmos DB ha introdotto diverse funzioni predefinite che consentono di eseguire query efficienti sul contenuto all'interno delle proprietà abilitate per la ricerca full-text. Queste funzioni sono: FullTextContains, FullTextContainsAll, FullTextContainsAny, che cercano parole chiave o parole chiave specifiche e FullTextScore, che restituisce il punteggio BM25 in base alle parole chiave specificate.

Annotazioni

FullTextScore può essere usato solo all'interno OrderBy per classificare i documenti in base al punteggio.

EF Core espone queste funzioni come parte di EF.Functions in modo che possano essere usate nelle query:

var cosmosBlogs = await context.Blogs.Where(x => EF.Functions.FullTextContainsAll(x.Contents, "database", "cosmos")).ToListAsync();

var keywords = new string[] { "AI", "agent", "breakthrough" };
var mostInteresting = await context.Blogs.OrderBy(x => EF.Functions.FullTextScore(x.Contents, keywords)).Take(5).ToListAsync();

La ricerca full-text può essere usata con la ricerca vettoriale nella stessa query (ad esempio, ricerca ibrida), combinando i risultati delle funzioni FullTextScore e VectorDistance. Può essere eseguito usando la funzione RRF (Reciprocal Rank Fusion), che EF Core fornisce anche all'interno di EF.Functions:

public class Blog
{
    ...

    public float[] Vector { get; set; }
    public string Contents { get; set; }
}

public class BloggingContext
{
    ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>(b =>
        {
            b.Property(x => x.Contents).EnableFullTextSearch();
            b.HasIndex(x => x.Contents).IsFullTextIndex();

            b.Property(x => x.Vector).IsVectorProperty(DistanceFunction.Cosine, dimensions: 1536);
            b.HasIndex(x => x.Vector).IsVectorIndex(VectorIndexType.Flat);
        });
    }
}

float[] myVector = /* generate vector data from text, image, etc. */
var hybrid = await context.Blogs.OrderBy(x => EF.Functions.Rrf(
        EF.Functions.FullTextScore(x.Contents, "database"), 
        EF.Functions.VectorDistance(x.Vector, myVector)))
    .Take(10)
    .ToListAsync();

Suggerimento

È possibile combinare più di due funzioni di assegnazione dei punteggi all'interno Rrf della chiamata, oltre a usare solo FullTextScore, o solo VectorDistance.