Condividi tramite


Ricerca e modelli di termini parziali con caratteri speciali (trattini, caratteri jolly, regex, pattern)

Una ricerca di termine parziale si riferisce a query costituite da frammenti di termini, in cui invece di un termine intero è possibile che sia presente solo l'inizio, la metà o la fine del termine (talvolta denominati prefisso, infisso o suffisso). Una ricerca di termini parziale può includere una combinazione di frammenti, spesso con caratteri speciali, ad esempio trattini o barre che fanno parte della stringa di query. I casi d'uso comuni includono parti di un numero di telefono, un URL, codici o parole composte sillabate.

I termini parziali e i caratteri speciali possono essere problematici se l'indice non ha un token che rappresenta il frammento di testo da cercare. Durante la fase di analisi lessicale dell'indicizzazione (presupponendo l'uso dell'analizzatore standard predefinito), i caratteri speciali vengono eliminati, le parole composte vengono suddivise e gli spazi vuoti vengono eliminati. Se si sta cercando un frammento di testo modificato durante l'analisi lessicale, la query ha esito negativo perché non viene trovata alcuna corrispondenza. Si consideri questo esempio: un numero di telefono come +1 (425) 703-6214 (tokenizzato come "1", "425", "703", "6214") non verrà visualizzato in una query "3-62" perché tale contenuto non esiste effettivamente nell'indice.

La soluzione consiste nel richiamare un analizzatore durante l'indicizzazione che mantenga una stringa completa, inclusi spazi e caratteri speciali se necessario, in modo da poter includere gli spazi e i caratteri nella stringa di query. La presenza di una stringa intera e non interrotta consente la corrispondenza dei criteri per le query "inizia con" o "termina con", in cui il modello fornito può essere valutato in base a un termine che non viene trasformato dall'analisi lessicale.

Se è necessario supportare scenari di ricerca che richiedono contenuti analizzati e non, è consigliabile creare due campi nell'indice, uno per ogni scenario. Un campo viene sottoposto ad analisi lessicale. Il secondo campo archivia una stringa intatta, usando un analizzatore di conservazione del contenuto che genera token di stringa interi per la corrispondenza dei criteri.

Azure AI Search analizza i termini interi con token nell'indice e non troverà una corrispondenza in un termine parziale, a meno che non si includano operatori segnaposto con caratteri jolly (* e ?) o non si formatti la query come espressione regolare.

I termini parziali vengono specificati usando queste tecniche:

  • Le Query di espressioni regolari possono essere qualsiasi espressione regolare valida in Apache Lucene.

  • Operatori di caratteri jolly con prefisso corrispondente si riferisce a un modello generalmente riconosciuto che include l'inizio di un termine, seguito da operatori di suffisso * o ?, ad esempio search=cap* che corrisponde a "Cap'n Jack's Waterfront Inn" o "Gacc Capital". La corrispondenza dei prefissi è supportata sia nella sintassi di query Lucene semplice che in quella completa.

  • Carattere jolly con infisso e suffisso corrispondenti posiziona gli operatori * e ? all'interno o all'inizio di un termine e richiede una sintassi di espressione regolare (dove l'espressione è racchiusa tra barre). Ad esempio, la stringa di query (search=/.*numeric.*/) restituisce i risultati per "alfanumerico" e "alfanumerici" come suffissi e corrispondenze di prefisso.

Per l'espressione regolare, il carattere jolly e la ricerca fuzzy, gli analizzatori non vengono usati in fase di query. Per questi moduli di query, che il parser rileva dalla presenza di operatori e delimitatori, la stringa di query viene passata al motore senza analisi lessicale. Per questi moduli di query, l'analizzatore specificato nel campo viene ignorato.

Nota

Quando una stringa di query parziale include caratteri, ad esempio barre in un frammento di URL, potrebbe essere necessario aggiungere caratteri di escape. In JSON una barra / viene preceduta da un carattere di escape con una barra rovesciata \. Di conseguenza, search=/.*microsoft.com\/azure\/.*/ è la sintassi per il frammento di URL "microsoft.com/azure/".

Risoluzione dei problemi di ricerca parziale/pattern

Quando è necessario cercare frammenti, modelli o caratteri speciali, è possibile eseguire l'override dell'analizzatore predefinito con un analizzatore personalizzato che opera su regole di tokenizzazione più semplici, mantenendo l'intera stringa nell'indice.

L'approccio è simile al seguente:

  1. Definire un secondo campo per archiviare una versione intatta della stringa (presupponendo che si desideri avere testo analizzato e non in fase di query)
  2. Valutare e scegliere tra i vari analizzatori che generano token al livello di granularità corretto
  3. Assegnare l'analizzatore al campo
  4. Compilare e testare l'indice

1 - Creare un campo dedicato

Gli analizzatori determinano il modo in cui i termini vengono tokenizzati in un indice. Poiché gli analizzatori vengono assegnati in base ai singoli campi, è possibile creare campi nell'indice per ottimizzare per scenari diversi. Ad esempio, è possibile definire "featureCode" e "featureCodeRegex" per supportare la normale ricerca full-text sul primo e i criteri di ricerca avanzati al secondo. Gli analizzatori assegnati a ogni campo determinano il modo in cui il contenuto di ogni campo viene tokenizzato nell'indice.

{
  "name": "featureCode",
  "type": "Edm.String",
  "retrievable": true,
  "searchable": true,
  "analyzer": null
},
{
  "name": "featureCodeRegex",
  "type": "Edm.String",
  "retrievable": true,
  "searchable": true,
  "analyzer": "my_custom_analyzer"
},

2 - Scegliere un analizzatore

Quando si sceglie un analizzatore che produce token a termine intero, gli analizzatori seguenti sono scelte comuni:

Analizzatore Comportamenti
analizzatori di linguaggi Mantiene i trattini in parole composte o stringhe, mutazioni vocali e forme verbali. Se i modelli di query includono trattini, l'uso di un analizzatore del linguaggio potrebbe essere sufficiente.
keyword Il contenuto dell'intero campo viene tokenizzato come singolo termine.
whitespace Separa solo gli spazi vuoti. I termini che includono trattini o altri caratteri vengono considerati come un singolo token.
analizzatore personalizzato (scelta consigliata) La creazione di un analizzatore personalizzato consente di specificare sia il tokenizer che il filtro del token. Gli analizzatori precedenti devono essere usati così come sono. Un analizzatore personalizzato consente di selezionare i tokenizzatori e i filtri di token da usare.

Una combinazione consigliata è il tokenizer di parole chiave con un filtro token in minuscolo. Da solo, l'analizzatore di parole chiave predefinito non imposta in minuscolo alcun testo maiuscolo, cosa che può causare l'esito negativo delle query. Un analizzatore personalizzato offre un meccanismo per l'aggiunta del filtro del token con lettere minuscole.

Usando un client REST, è possibile aggiungere la chiamata REST dell'analizzatore di test per esaminare l'output con token.

L'indice deve esistere nel servizio di ricerca, ma può essere vuoto. Dato un indice esistente e un campo contenente trattini o termini parziali, è possibile provare vari analizzatori su termini specifici per vedere quali token vengono generati.

  1. Prima di tutto, controllare l'analizzatore Standard per vedere come i termini vengono tokenizzati per impostazione predefinita.

    {
    "text": "SVP10-NOR-00",
    "analyzer": "standard"
    }
    
  2. Valutare la risposta per vedere in che modo il testo viene tokenizzato all'interno dell'indice. Si noti che ogni termine include lettere minuscole, trattini rimossi e sottostringhe suddivise in singoli token. Nei risultati verranno restituite solo le query che corrispondono a questi token. Una query che include "10-NOR" avrà esito negativo.

    {
        "tokens": [
            {
                "token": "svp10",
                "startOffset": 0,
                "endOffset": 5,
                "position": 0
            },
            {
                "token": "nor",
                "startOffset": 6,
                "endOffset": 9,
                "position": 1
            },
            {
                "token": "00",
                "startOffset": 10,
                "endOffset": 12,
                "position": 2
            }
        ]
    }
    
  3. Modificare ora la richiesta per usare l'analizzatore whitespace o keyword:

    {
    "text": "SVP10-NOR-00",
    "analyzer": "keyword"
    }
    
  4. Questa volta, la risposta è costituita da un singolo token, con maiuscole e minuscole e trattini mantenuti come parte della stringa. Se è necessario cercare un criterio o un termine parziale, ad esempio "10-NOR", il motore di query ora ha la base per trovare una corrispondenza.

    {
    
        "tokens": [
            {
                "token": "SVP10-NOR-00",
                "startOffset": 0,
                "endOffset": 12,
                "position": 0
            }
        ]
    }
    

Importante

Tenere presente che i parser di query spesso cambiano i termini in minuscolo in un'espressione di ricerca durante la compilazione dell'albero delle query. Se si usa un analizzatore che non inserisce input di testo in lettere minuscole durante l'indicizzazione e non si ottengono risultati previsti, questo potrebbe essere il motivo. La soluzione consiste nell'aggiungere un filtro token per il minuscolo, come descritto nella sezione "Usare analizzatori personalizzati" di seguito.

3 - Configurare un analizzatore

Indipendentemente dal fatto che si stiano valutando gli analizzatori o si stia procedendo con una configurazione specifica, sarà necessario specificare l'analizzatore nella definizione del campo ed eventualmente configurare l'analizzatore stesso se non si usa quello predefinito. Quando si scambiano gli analizzatori, in genere è necessario ricompilare l'indice (eliminare, ricreare e ricaricare).

Usare analizzatori predefiniti

Gli analizzatori predefiniti possono essere specificati in base al nome in una proprietà analyzer di una definizione di campo, senza alcuna configurazione aggiuntiva necessaria nell'indice. Nell'esempio seguente viene illustrato come impostare l'analizzatore whitespace su un campo.

Per altri scenari e altre informazioni su altri analizzatori predefiniti, vedere Analizzatori predefiniti.

    {
      "name": "phoneNumber",
      "type": "Edm.String",
      "key": false,
      "retrievable": true,
      "searchable": true,
      "analyzer": "whitespace"
    }

Usare analizzatori personalizzati

Se si usa un analizzatore personalizzato, definirlo nell'indice con una combinazione definita dall'utente di tokenizer, filtro token, con possibili impostazioni di configurazione. Fare quindi riferimento a tale definizione in una definizione di campo, proprio come si farebbe con un analizzatore predefinito.

Quando l'obiettivo è la tokenizzazione a termini interi, è consigliabile un analizzatore personalizzato costituito da un tokenizer di parole chiave e un filtro token per il minuscolo.

  • Il tokenizer di parole chiave crea un singolo token per l'intero contenuto di un campo.
  • Il filtro del token in minuscolo trasforma le lettere maiuscole in testo minuscolo. I parser di query in genere rendono minuscolo qualsiasi input di testo maiuscolo. La combinazione di maiuscole e minuscole rende omogenei gli input con i termini tokenizzati.

L'esempio seguente illustra un analizzatore personalizzato che fornisce il tokenizer di parole chiave e un filtro token per il minuscolo.

{
"fields": [
  {
    "name": "accountNumber",
    "analyzer":"myCustomAnalyzer",
    "type": "Edm.String",
    "searchable": true,
    "filterable": true,
    "retrievable": true,
    "sortable": false,
    "facetable": false
  }
],

"analyzers": [
  {
    "@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
    "name":"myCustomAnalyzer",
    "charFilters":[],
    "tokenizer":"keyword_v2",
    "tokenFilters":["lowercase"]
  }
],
"tokenizers":[],
"charFilters": [],
"tokenFilters": []
}

Nota

Il tokenizer keyword_v2 e il filtro token lowercase sono noti al sistema e usano le relative configurazioni predefinite, motivo per cui è possibile farvi riferimento per nome senza doverli prima definire.

4 - Compilazione e test

Dopo aver definito un indice con analizzatori e definizioni di campo che supportano lo scenario, caricare documenti con stringhe rappresentative in modo da poter testare query di stringa parziali.

Usare un client REST per eseguire query su termini parziali e caratteri speciali descritti in questo articolo.

Le sezioni precedenti illustrano la logica. Questa sezione illustra ogni API che è necessario chiamare durante il test della soluzione.

  • Elimina indice rimuove un indice esistente con lo stesso nome in modo da poterlo ricreare.

  • Crea indice crea la struttura dell'indice nel servizio di ricerca, inclusi le definizioni dell'analizzatore e i campi con una specifica dell'analizzatore.

  • Carica documenti importa i documenti con la stessa struttura dell'indice, nonché il contenuto ricercabile. Dopo questo passaggio, l'indice è pronto per eseguire query o test.

  • Analizzatore test è stato introdotto in Impostare un analizzatore. Testare alcune delle stringhe nell'indice usando vari analizzatori per comprendere come vengono tokenizzati i termini.

  • Ricerca documenti spiega come costruire una richiesta di query usando una sintassi semplice o la sintassi Lucene completa per le espressioni regolari e con caratteri jolly.

    Per le query con termini parziali, ad esempio l'esecuzione di query su "3-6214" per trovare una corrispondenza in "+1 (425) 703-6214", è possibile usare la sintassi semplice: search=3-6214&queryType=simple.

    Per le query di prefisso e suffisso, ad esempio l'esecuzione di query su "num" o "numerico per trovare una corrispondenza in "alfanumerico", usare la sintassi Lucene completa e un'espressione regolare: search=/.*num.*/&queryType=full

Ottimizzazione delle query di prefisso e suffisso

La corrispondenza di prefissi e suffissi usando l'analizzatore predefinito richiede funzionalità di query aggiuntive. I prefissi richiedono la ricerca con caratteri jolly e i suffissi richiedono la ricerca di espressioni regolari. Entrambe queste funzionalità possono ridurre le prestazioni delle query.

Nell'esempio seguente viene aggiunto un EdgeNGramTokenFilter per rendere più veloci le corrispondenze di prefisso o suffisso. I token vengono generati in combinazioni da 2 a 25 caratteri. Ecco un esempio di progressione da due a sette token: MS, MSFT, MSFT, MSFT/, MSFT/S, MSFT/SQ, MSFT/SQL. EdgeNGramTokenFilter richiede un parametro side che determina il lato della stringa da cui vengono generate le combinazioni di caratteri. Usare front per le query di prefisso e back per le query di suffisso.

La tokenizzazione aggiuntiva comporta un indice più grande. Se si dispone di capacità sufficiente per supportare l'indice più grande, questo approccio con tempi di risposta più rapidi potrebbe essere la soluzione migliore.

{
"fields": [
  {
    "name": "accountNumber_prefix",
    "indexAnalyzer": "ngram_front_analyzer",
    "searchAnalyzer": "keyword",
    "type": "Edm.String",
    "searchable": true,
    "filterable": false,
    "retrievable": true,
    "sortable": false,
    "facetable": false
  },
  {
    "name": "accountNumber_suffix",
    "indexAnalyzer": "ngram_back_analyzer",
    "searchAnalyzer": "keyword",
    "type": "Edm.String",
    "searchable": true,
    "filterable": false,
    "retrievable": true,
    "sortable": false,
    "facetable": false
  }
],

"analyzers": [
  {
    "@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
    "name":"ngram_front_analyzer",
    "charFilters":[],
    "tokenizer":"keyword_v2",
    "tokenFilters":["lowercase", "front_edgeNGram"]
  },
  {
    "@odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
    "name":"ngram_back_analyzer",
    "charFilters":[],
    "tokenizer":"keyword_v2",
    "tokenFilters":["lowercase", "back_edgeNGram"]
  }
],
"tokenizers":[],
"charFilters": [],
"tokenFilters": [
  {
    "@odata.type":"#Microsoft.Azure.Search.EdgeNGramTokenFilterV2",
    "name":"front_edgeNGram",
    "minGram": 2,
    "maxGram": 25,
    "side": "front"
  },
  {
    "@odata.type":"#Microsoft.Azure.Search.EdgeNGramTokenFilterV2",
    "name":"back_edgeNGram",
    "minGram": 2,
    "maxGram": 25,
    "side": "back"
  }
]
}

Per cercare numeri di account che iniziano con 123, è possibile usare la query seguente:

{
  "search": "123",
  "searchFields": "accountNumber_prefix"
}

Per cercare numeri di account che terminano con 456, è possibile usare la query seguente:

{
  "search": "456",
  "searchFields": "accountNumber_suffix"
}

Passaggi successivi

Questo articolo illustra in che modo gli analizzatori contribuiscono sia ai problemi di query che a risolverli. Come passaggio successivo, esaminare più in dettaglio gli analizzatori che influiscono sull'indicizzazione e sull'elaborazione delle query.