Esempi di query di ricerca "semplici" in Ricerca di intelligenza artificiale di Azure

In Ricerca di intelligenza artificiale di Azure la sintassi di query semplice richiama il parser di query predefinito per la ricerca full-text. Il parser è veloce e gestisce scenari comuni, tra cui la ricerca full-text, la ricerca filtrata e in base a facet e la ricerca con prefisso. Questo articolo usa esempi per illustrare l'utilizzo della sintassi semplice in una richiesta di ricerca di documenti (API REST).

Nota

Una sintassi di query alternativa è Full Lucene, che supporta strutture di query più complesse, ad esempio la ricerca fuzzy e con caratteri jolly. Per altre informazioni ed esempi, vedere Usare la sintassi Lucene completa.

Indice di esempio hotels

Le query seguenti sono basate su hotels-sample-index, che è possibile creare seguendo le istruzioni riportate in questa guida introduttiva.

Le query di esempio sono articolate usando l'API REST e le richieste POST. È possibile incollarli ed eseguirli in un client REST. In alternativa, usare la visualizzazione JSON di Esplora ricerche nella portale di Azure. Nella visualizzazione JSON è possibile incollare gli esempi di query illustrati qui in questo articolo.

Le intestazioni della richiesta devono avere i valori seguenti:

Chiave valore
Content-Type application/json
api-key <your-search-service-api-key>, query o chiave di amministrazione

I parametri URI devono includere l'endpoint del servizio di ricerca con il nome dell'indice, le raccolte docs, il comando di ricerca e la versione dell'API, in modo analogo all'esempio seguente:

https://{{service-name}}.search.windows.net/indexes/hotels-sample-index/docs/search?api-version=2023-11-01

Il corpo della richiesta deve essere formato come JSON valido:

{
    "search": "*",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Tags, Description",
    "count": true
}
  • "search" impostato su * è una query non specificata, equivalente a una ricerca null o vuota. Non è particolarmente utile, ma è la ricerca più semplice che è possibile eseguire e mostra tutti i campi recuperabili nell'indice, con tutti i valori.

  • "queryType" impostato su "simple" è l'impostazione predefinita e può essere omesso, ma è incluso per rafforzare ulteriormente che gli esempi di query in questo articolo sono espressi nella sintassi semplice.

  • "select" impostato su un elenco delimitato da virgole di campi viene usato per la composizione dei risultati della ricerca, inclusi solo i campi utili nel contesto dei risultati della ricerca.

  • "count" restituisce il numero di documenti corrispondenti ai criteri di ricerca. In una stringa di ricerca vuota, il conteggio è tutti i documenti nell'indice (50 nell'indice hotels-sample-index).

La ricerca full-text può essere un numero qualsiasi di termini autonomi o frasi racchiuse tra virgolette, con o senza operatori booleani.

POST /indexes/hotel-samples-index/docs/search?api-version=2023-11-01
{
    "search": "pool spa +airport",
    "searchMode": "any",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Description",
    "count": true
}

Una ricerca di parole chiave composta da termini o frasi importanti tende a funzionare meglio. I campi stringa vengono sottoposti a analisi del testo durante l'indicizzazione e l'esecuzione di query, eliminando parole non essenziali come "the", "and", "it". Per vedere come una stringa di query viene tokenizzata nell'indice, passare la stringa in una chiamata Analyze Text all'indice.

Il parametro "searchMode" controlla la precisione e il richiamo. Se si desidera più richiamare, usare il valore predefinito "any", che restituisce un risultato se una parte della stringa di query corrisponde. Se si preferisce la precisione, dove tutte le parti della stringa devono essere abbinate, impostare searchMode su "all". Provare la query precedente in entrambi i modi per vedere come searchMode modifica il risultato.

La risposta per la query "pool spa +airport" dovrebbe essere simile all'esempio seguente, tagliato per brevità.

"@odata.count": 6,
"value": [
    {
        "@search.score": 7.3617697,
        "HotelId": "21",
        "HotelName": "Nova Hotel & Spa",
        "Description": "1 Mile from the airport.  Free WiFi, Outdoor Pool, Complimentary Airport Shuttle, 6 miles from the beach & 10 miles from downtown.",
        "Category": "Resort and Spa",
        "Tags": [
            "pool",
            "continental breakfast",
            "free parking"
        ]
    },
    {
        "@search.score": 2.5560288,
        "HotelId": "25",
        "HotelName": "Scottish Inn",
        "Description": "Newly Redesigned Rooms & airport shuttle.  Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.",
        "Category": "Luxury",
        "Tags": [
            "24-hour front desk service",
            "continental breakfast",
            "free wifi"
        ]
    },
    {
        "@search.score": 2.2988036,
        "HotelId": "35",
        "HotelName": "Suites At Bellevue Square",
        "Description": "Luxury at the mall.  Located across the street from the Light Rail to downtown.  Free shuttle to the mall and airport.",
        "Category": "Resort and Spa",
        "Tags": [
            "continental breakfast",
            "air conditioning",
            "24-hour front desk service"
        ]
    }
]

Si noti il punteggio di ricerca nella risposta. Si tratta del punteggio di pertinenza della corrispondenza. Per impostazione predefinita, un servizio di ricerca restituisce le prime 50 corrispondenze in base a questo punteggio.

I punteggi uniformi di "1,0" si verificano quando non è presente alcuna classificazione, perché la ricerca non era full-text o perché non sono stati specificati criteri. Ad esempio, in una ricerca vuota (search=*), le righe tornano in ordine arbitrario. Quando si includono criteri effettivi, si noterà che i punteggi di ricerca si evolvono in valori significativi.

Esempio 2: ricerca per ID

Quando si restituiscono i risultati della ricerca in una query, un passaggio successivo logico consiste nel fornire una pagina dei dettagli che include più campi del documento. In questo esempio viene illustrato come restituire un singolo documento usando il documento di ricerca passando l'ID documento.

GET /indexes/hotels-sample-index/docs/41?api-version=2023-11-01

Tutti i documenti dispongono di un identificatore unico. Se si usa il portale, selezionare l'indice nella scheda Indici e quindi esaminare le definizioni dei campi per determinare quale campo è la chiave. Usando REST, la chiamata Get Index restituisce la definizione di indice nel corpo della risposta.

La risposta per la query precedente è costituita dal documento la cui chiave è 41. Qualsiasi campo contrassegnato come "recuperabile" nella definizione dell'indice può essere restituito nei risultati della ricerca e sottoposto a rendering nell'app.

{
    "HotelId": "41",
    "HotelName": "Ocean Air Motel",
    "Description": "Oceanfront hotel overlooking the beach features rooms with a private balcony and 2 indoor and outdoor pools. Various shops and art entertainment are on the boardwalk, just steps away.",
    "Description_fr": "L'hôtel front de mer surplombant la plage dispose de chambres avec balcon privé et 2 piscines intérieures et extérieures. Divers commerces et animations artistiques sont sur la promenade, à quelques pas.",
    "Category": "Budget",
    "Tags": [
        "pool",
        "air conditioning",
        "bar"
    ],
    "ParkingIncluded": true,
    "LastRenovationDate": "1951-05-10T00:00:00Z",
    "Rating": 3.5,
    "Location": {
        "type": "Point",
        "coordinates": [
            -157.846817,
            21.295841
        ],
        "crs": {
            "type": "name",
            "properties": {
                "name": "EPSG:4326"
            }
        }
    },
    "Address": {
        "StreetAddress": "1450 Ala Moana Blvd 2238 Ala Moana Ctr",
        "City": "Honolulu",
        "StateProvince": "HI",
        "PostalCode": "96814",
        "Country": "USA"
    }
}

Esempio 3: Filtrare in base al testo

La sintassi del filtro è un'espressione OData che è possibile usare da sola o con search. Usato insieme, filter viene applicato prima all'intero indice e quindi la ricerca viene eseguita sui risultati del filtro. I filtri quindi possono essere un'utile tecnica per migliorare le prestazioni delle query perché riducono il set di documenti che la query di ricerca deve elaborare.

I filtri possono essere definiti in qualsiasi campo contrassegnato come filterable nella definizione dell'indice. Per hotels-sample-index, i campi filtrabili includono Category, Tags, ParkingIncluded, Rating e la maggior parte dei campi Address.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "art tours",
    "queryType": "simple",
    "filter": "Category eq 'Resort and Spa'",
    "searchFields": "HotelName,Description,Category",
    "select": "HotelId,HotelName,Description,Category",
    "count": true
}

La risposta per la query precedente ha come ambito solo gli hotel classificati come "Report e Spa" e che includono i termini "arte" o "tour". In questo caso, c'è solo una corrispondenza.

{
    "@search.score": 2.8576312,
    "HotelId": "31",
    "HotelName": "Santa Fe Stay",
    "Description": "Nestled on six beautifully landscaped acres, located 2 blocks from the Plaza. Unwind at the spa and indulge in art tours on site.",
    "Category": "Resort and Spa"
}

Esempio 4: Funzioni di filtro

Le espressioni di filtro possono includere funzioni "search.ismatch" e "search.ismatchscoring", che consentono di compilare una query di ricerca all'interno del filtro. Questa espressione di filtro usa un carattere jolly gratuito per selezionare servizi tra cui wi-fi gratuito, parcheggio gratuito e così via.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
  {
    "search": "",
    "filter": "search.ismatch('free*', 'Tags', 'full', 'any')",
    "select": "HotelId, HotelName, Category, Description",
    "count": true
  }

Risposta per la query precedente corrisponde a 19 hotel che offrono servizi gratuiti. Si noti che il punteggio di ricerca è un'uniforme "1,0" nei risultati. Ciò è dovuto al fatto che l'espressione di ricerca è null o vuota, generando corrispondenze di filtro verbatim, ma nessuna ricerca full-text. I punteggi di pertinenza vengono restituiti solo nella ricerca full-text. Se si usano filtri senza search, assicurarsi di disporre di campi ordinabili sufficienti in modo da poter controllare la classificazione della ricerca.

"@odata.count": 19,
"value": [
    {
        "@search.score": 1.0,
        "HotelId": "31",
        "HotelName": "Santa Fe Stay",
        "Tags": [
            "view",
            "restaurant",
            "free parking"
        ]
    },
    {
        "@search.score": 1.0,
        "HotelId": "27",
        "HotelName": "Super Deluxe Inn & Suites",
        "Tags": [
            "bar",
            "free wifi"
        ]
    },
    {
        "@search.score": 1.0,
        "HotelId": "39",
        "HotelName": "Whitefish Lodge & Suites",
        "Tags": [
            "continental breakfast",
            "free parking",
            "free wifi"
        ]
    },
    {
        "@search.score": 1.0,
        "HotelId": "11",
        "HotelName": "Regal Orb Resort & Spa",
        "Tags": [
            "free wifi",
            "restaurant",
            "24-hour front desk service"
        ]
    },

Esempio 5: Filtri di intervallo

Il filtro di intervalli è supportato tramite espressioni di filtro per qualsiasi tipo di dati. Negli esempi seguenti vengono illustrati gli intervalli numerici e di stringhe. I tipi di dati sono importanti nei filtri di intervallo e funzionano in modo ottimale quando i dati numerici si trovano nei campi numerici e i dati di tipo stringa nei campi stringa. I dati numerici nei campi stringa non sono adatti per gli intervalli perché le stringhe numeriche non sono confrontabili.

La query seguente è un intervallo numerico. In hotels-sample-index l'unico campo numerico filtrabile è Rating.

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Rating ge 2 and Rating lt 4",
    "select": "HotelId, HotelName, Rating",
    "orderby": "Rating desc",
    "count": true
}

La risposta per questa query dovrebbe essere simile all'esempio seguente, tagliata per brevità.

"@odata.count": 27,
"value": [
    {
        "@search.score": 1.0,
        "HotelId": "22",
        "HotelName": "Stone Lion Inn",
        "Rating": 3.9
    },
    {
        "@search.score": 1.0,
        "HotelId": "25",
        "HotelName": "Scottish Inn",
        "Rating": 3.8
    },
    {
        "@search.score": 1.0,
        "HotelId": "2",
        "HotelName": "Twin Dome Motel",
        "Rating": 3.6
    }
...

La query successiva è un filtro di intervallo su un campo stringa (Indirizzo/StatoProvince):

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Address/StateProvince ge 'A*' and Address/StateProvince lt 'D*'",
    "select": "HotelId, HotelName, Address/StateProvince",
    "count": true
}

La risposta per questa query dovrebbe essere simile all'esempio seguente, tagliata per brevità. In questo esempio non è possibile ordinare in base a StateProvince perché il campo non è attribuito come "ordinabile" nella definizione dell'indice.

"@odata.count": 9,
"value": [
    {
        "@search.score": 1.0,
        "HotelId": "9",
        "HotelName": "Smile Hotel",
        "Address": {
            "StateProvince": "CA "
        }
    },
    {
        "@search.score": 1.0,
        "HotelId": "39",
        "HotelName": "Whitefish Lodge & Suites",
        "Address": {
            "StateProvince": "CO"
        }
    },
    {
        "@search.score": 1.0,
        "HotelId": "7",
        "HotelName": "Countryside Resort",
        "Address": {
            "StateProvince": "CA "
        }
    },
...

L'indice hotels-sample include un campo Location con coordinate di latitudine e longitudine. Questo esempio usa la funzione geo.distance che applica il filtro ai documenti all'interno della circonferenza di un punto di partenza, fino a una distanza arbitraria (in chilometri) specificata. È possibile modificare l'ultimo valore nella query (10) per ridurre o ingrandire la superficie della query.

POST /indexes/v/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "geo.distance(Location, geography'POINT(-122.335114 47.612839)') le 10",
    "select": "HotelId, HotelName, Address/City, Address/StateProvince",
    "count": true
}

La risposta per questa query restituisce tutti gli hotel entro una distanza di 10 chilometri delle coordinate specificate:

{
    "@odata.count": 3,
    "value": [
        {
            "@search.score": 1.0,
            "HotelId": "45",
            "HotelName": "Arcadia Resort & Restaurant",
            "Address": {
                "City": "Seattle",
                "StateProvince": "WA"
            }
        },
        {
            "@search.score": 1.0,
            "HotelId": "24",
            "HotelName": "Gacc Capital",
            "Address": {
                "City": "Seattle",
                "StateProvince": "WA"
            }
        },
        {
            "@search.score": 1.0,
            "HotelId": "16",
            "HotelName": "Double Sanctuary Resort",
            "Address": {
                "City": "Seattle",
                "StateProvince": "WA"
            }
        }
    ]
}

Esempio 7: valori booleani con searchMode

La sintassi semplice supporta gli operatori booleani sotto forma di caratteri (+, -, |) per supportare la logica di query AND, OR e NOT. La ricerca booleana si comporta come previsto, con alcune eccezioni degne di nota.

Negli esempi precedenti, il searchMode parametro è stato introdotto come meccanismo per influenzare la precisione e il richiamo, con "searchMode": "any" il favore del richiamo (un documento che soddisfa uno dei criteri è considerato una corrispondenza) e "searchMode=all" che favorisce la precisione (tutti i criteri devono essere corrispondenti in un documento).

Nel contesto di una ricerca booleana, l'impostazione predefinita "searchMode": "any" può generare confusione se si esegue lo stack di una query con più operatori e si ottengono risultati più ampi anziché più stretti. Ciò è particolarmente vero con NOT, dove i risultati includono tutti i documenti "non contenenti" un termine o una frase specifica.

Di seguito ne viene illustrato un esempio. Viene restituita la query seguente con searchMode (qualsiasi), vengono restituiti 42 documenti contenenti il termine "ristorante", oltre a tutti i documenti che non hanno la frase "aria condizionata".

Si noti che non c'è spazio tra l'operatore booleano (-) e la frase "aria condizionata".

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "restaurant -\"air conditioning\"",
    "searchMode": "any",
    "searchFields": "Tags",
    "select": "HotelId, HotelName, Tags",
    "count": true
}

La modifica di in "searchMode": "all" applica un effetto cumulativo sui criteri e restituisce un set di risultati più piccolo (7 corrispondenze) costituito da documenti contenenti il termine "ristorante", meno quelli contenenti la frase "aria condizionata".

La risposta per questa query sarà ora simile all'esempio seguente, tagliata per brevità.

"@odata.count": 7,
"value": [
    {
        "@search.score": 2.5460577,
        "HotelId": "11",
        "HotelName": "Regal Orb Resort & Spa",
        "Tags": [
            "free wifi",
            "restaurant",
            "24-hour front desk service"
        ]
    },
    {
        "@search.score": 2.166792,
        "HotelId": "10",
        "HotelName": "Countryside Hotel",
        "Tags": [
            "24-hour front desk service",
            "coffee in lobby",
            "restaurant"
        ]
    },
...

Esempio 8: paging dei risultati

Negli esempi precedenti sono stati illustrati i parametri che influiscono sulla composizione dei risultati della ricerca, inclusi select quelli che determinano quali campi si trovano in un risultato, ordinano gli ordini e come includere un conteggio di tutte le corrispondenze. Questo esempio è una continuazione della composizione dei risultati di ricerca sotto forma di parametri di paging che consentono di raggruppare in batch il numero di risultati visualizzati in una determinata pagina.

Per impostazione predefinita, un servizio di ricerca restituisce le prime 50 corrispondenze. Per controllare il numero di corrispondenze in ogni pagina, usare top per definire le dimensioni del batch e quindi usare skip per raccogliere i batch successivi.

L'esempio seguente usa un filtro e un ordinamento per il campo Rating (Rating è filtrabile e ordinabile) perché è più facile visualizzare gli effetti del paging sui risultati ordinati. In una normale query di ricerca completa, le corrispondenze principali vengono classificate e paging in @search.scorebase a .

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName, Rating",
    "orderby": "Rating desc",
    "top": "5",
    "count": true
}

La query trova 21 documenti corrispondenti, ma poiché è stato specificato top, la risposta restituisce solo le prime cinque corrispondenze, con valutazioni a partire dalle 4.9 e terminando alle 4.7 con "Lady of the Lake B & B".

Per ottenere i successivi 5, ignorare il primo batch:

POST /indexes/hotels-sample-index/docs/search?api-version=2023-11-01
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName, Rating",
    "orderby": "Rating desc",
    "top": "5",
    "skip": "5",
    "count": true
}

La risposta per il secondo batch ignora le prime cinque partite, restituendo i cinque successivi, a partire da "Pull'r Inn Motel". Per continuare con più batch, mantenere top a 5 e quindi incrementare skip di 5 per ogni nuova richiesta (skip=5, skip=10, skip=15 e così via).

"value": [
    {
        "@search.score": 1.0,
        "HotelName": "Pull'r Inn Motel",
        "Rating": 4.7
    },
    {
        "@search.score": 1.0,
        "HotelName": "Sublime Cliff Hotel",
        "Rating": 4.6
    },
    {
        "@search.score": 1.0,
        "HotelName": "Antiquity Hotel",
        "Rating": 4.5
    },
    {
        "@search.score": 1.0,
        "HotelName": "Nordick's Motel",
        "Rating": 4.5
    },
    {
        "@search.score": 1.0,
        "HotelName": "Winter Panorama Resort",
        "Rating": 4.5
    }
]

Passaggi successivi

Dopo aver fatto pratica con la sintassi di query di base, provare a specificare le query nel codice. Il collegamento seguente illustra come configurare le query di ricerca usando gli SDK di Azure.

Altri riferimenti alla sintassi, architettura di query ed esempi sono disponibili nei collegamenti seguenti: