Modellare tipi di dati complessi in Ricerca di intelligenza artificiale di Azure

I set di dati esterni usati per popolare un indice di Ricerca intelligenza artificiale di Azure possono venire in molte forme. In alcuni casi includono sottostruttura gerarchiche o annidate. Alcuni esempi possono includere più indirizzi per un singolo cliente, più colori e dimensioni per un singolo SKU, più autori di un singolo libro e così via. In termini di modellazione, è possibile che queste strutture vengano definite tipi di dati complessi, composti, compositi o aggregati . Il termine Ricerca intelligenza artificiale di Azure usa per questo concetto è un tipo complesso. In Ricerca di intelligenza artificiale di Azure i tipi complessi vengono modellati usando campi complessi. Un campo complesso è un campo contenente elementi figlio (campi secondari) che possono essere di qualsiasi tipo di dati, inclusi altri tipi complessi. Questa operazione funziona in modo analogo ai tipi di dati strutturati in un linguaggio di programmazione.

I campi complessi rappresentano un singolo oggetto nel documento o una matrice di oggetti, a seconda del tipo di dati. I campi di tipo Edm.ComplexType rappresentano singoli oggetti, mentre i campi di tipo Collection(Edm.ComplexType) rappresentano matrici di oggetti.

Ricerca di intelligenza artificiale di Azure supporta in modo nativo tipi e raccolte complessi. Questi tipi consentono di modellare quasi qualsiasi struttura JSON in un indice di Ricerca di intelligenza artificiale di Azure. Nelle versioni precedenti delle API di Ricerca intelligenza artificiale di Azure è possibile importare solo set di righe bidimensionati. Nella versione più recente, l'indice può ora corrispondere più strettamente ai dati di origine. In altre parole, se i dati di origine hanno tipi complessi, anche l'indice può avere tipi complessi.

Per iniziare, è consigliabile usare il set di dati Hotels, che è possibile caricare nella procedura guidata Importa dati nella portale di Azure. La procedura guidata rileva tipi complessi nell'origine e suggerisce uno schema di indice basato sulle strutture rilevate.

Nota

Il supporto per i tipi complessi è diventato disponibile a livello generale a partire da api-version=2019-05-06.

Se la soluzione di ricerca è basata su soluzioni alternative precedenti di set di dati bidimensionati in una raccolta, è necessario modificare l'indice in modo da includere tipi complessi come supportati nella versione più recente dell'API. Per altre informazioni sull'aggiornamento delle versioni dell'API, vedere Eseguire l'aggiornamento alla versione più recente dell'API REST o eseguire l'aggiornamento alla versione più recente di .NET SDK.

Esempio di struttura complessa

Il documento JSON seguente è costituito da campi semplici e campi complessi. I campi complessi, ad esempio Address e Rooms, dispongono di sottocampi. Address ha un singolo set di valori per tali sottocampi, poiché si tratta di un singolo oggetto nel documento. Al contrario, Rooms dispone di più set di valori per i relativi sottocampi, uno per ogni oggetto dell'insieme.

{
  "HotelId": "1",
  "HotelName": "Secret Point Motel",
  "Description": "Ideally located on the main commercial artery of the city in the heart of New York.",
  "Tags": ["Free wifi", "on-site parking", "indoor pool", "continental breakfast"],
  "Address": {
    "StreetAddress": "677 5th Ave",
    "City": "New York",
    "StateProvince": "NY"
  },
  "Rooms": [
    {
      "Description": "Budget Room, 1 Queen Bed (Cityside)",
      "RoomNumber": 1105,
      "BaseRate": 96.99,
    },
    {
      "Description": "Deluxe Room, 2 Double Beds (City View)",
      "Type": "Deluxe Room",
      "BaseRate": 150.99,
    }
    . . .
  ]
}

Indicizzazione di tipi complessi

Durante l'indicizzazione, è possibile avere un massimo di 3000 elementi in tutte le raccolte complesse all'interno di un singolo documento. Un elemento di una raccolta complessa è un membro di tale raccolta, quindi nel caso di Rooms (l'unica raccolta complessa nell'esempio Hotel), ogni stanza è un elemento. Nell'esempio precedente, se il "Secret Point Motel" aveva 500 camere, il documento dell'hotel avrebbe 500 elementi della stanza. Per le raccolte complesse annidate, viene conteggiato anche ogni elemento annidato, oltre all'elemento esterno (padre).

Questo limite si applica solo a raccolte complesse e non a tipi complessi (ad esempio Address) o raccolte di stringhe (ad esempio Tag).

Creare campi complessi

Come per qualsiasi definizione di indice, è possibile usare il portale, l'API REST o .NET SDK per creare uno schema che include tipi complessi.

Altri SDK di Azure forniscono esempi in Python, Java e JavaScript.

  1. Accedere al portale di Azure.

  2. Nella pagina Panoramica del servizio di ricerca selezionare la scheda Indici.

  3. Aprire un indice esistente o creare un nuovo indice.

  4. Selezionare la scheda Campi e quindi selezionare Aggiungi campo. Viene aggiunto un campo vuoto. Se si usa una raccolta di campi esistenti, scorrere verso il basso per configurare il campo.

  5. Assegnare un nome al campo e impostare il tipo su Edm.ComplexType o Collection(Edm.ComplexType).

  6. Selezionare i puntini di sospensione all'estrema destra, quindi selezionare Aggiungi campo o Aggiungi sottocampo e quindi assegnare attributi.

Aggiornare campi complessi

Tutte le regole di reindicizzazione applicabili ai campi in generale si applicano comunque a campi complessi. Riformulando alcune delle regole principali, l'aggiunta di un campo a un tipo complesso non richiede una ricompilazione dell'indice, ma la maggior parte delle modifiche.

Aggiornamenti strutturali alla definizione

È possibile aggiungere nuovi campi secondari a un campo complesso in qualsiasi momento senza la necessità di una ricompilazione dell'indice. Ad esempio, l'aggiunta di "ZipCode" a Address o "Servizi" a Rooms è consentita, proprio come l'aggiunta di un campo di primo livello a un indice. I documenti esistenti hanno un valore Null per i nuovi campi fino a quando non si popolano in modo esplicito tali campi aggiornando i dati.

Si noti che all'interno di un tipo complesso, ogni sottocampo ha un tipo e può avere attributi, proprio come i campi di primo livello

Aggiornamenti dei dati

L'aggiornamento di documenti esistenti in un indice con l'azione upload funziona allo stesso modo per i campi complessi e semplici: tutti i campi vengono sostituiti. Tuttavia, merge (o mergeOrUpload quando applicato a un documento esistente) non funziona come in tutti i campi. In particolare, merge non supporta l'unione di elementi all'interno di una raccolta. Questa limitazione esiste per le raccolte di tipi primitivi e raccolte complesse. Per aggiornare una raccolta, è necessario recuperare il valore completo della raccolta, apportare modifiche e quindi includere la nuova raccolta nella richiesta DELL'API Index.

Cerca campi complessi

Le espressioni di ricerca in formato libero funzionano come previsto con tipi complessi. Se un campo o un sottocampo ricercabile in qualsiasi punto di un documento corrisponde, il documento stesso è una corrispondenza.

Le query ottengono più sfumature quando si hanno più termini e operatori e alcuni termini hanno nomi di campo specificati, come è possibile con la sintassi Lucene. Ad esempio, questa query tenta di trovare la corrispondenza con due termini, "Portland" e "OR", rispetto a due sottocampi del campo Indirizzo:

search=Address/City:Portland AND Address/State:OR

Le query di questo tipo non sono correlate per la ricerca full-text, a differenza dei filtri. Nei filtri le query sui sottocampi di una raccolta complessa vengono correlate usando variabili di intervallo in any o all. La query Lucene precedente restituisce documenti contenenti sia "Portland, Maine" che "Portland, Oregon", insieme ad altre città in Oregon. Ciò si verifica perché ogni clausola si applica a tutti i valori del relativo campo nell'intero documento, quindi non esiste alcun concetto di "documento secondario corrente". Per altre informazioni su questo argomento, vedere Informazioni sui filtri di raccolta OData in Ricerca di intelligenza artificiale di Azure.

Selezionare campi complessi

Il $select parametro viene usato per scegliere i campi restituiti nei risultati della ricerca. Per utilizzare questo parametro per selezionare campi secondari specifici di un campo complesso, includere il campo padre e il sottocampo separati da una barra (/).

$select=HotelName, Address/City, Rooms/BaseRate

I campi devono essere contrassegnati come Recuperabili nell'indice se si desidera nei risultati della ricerca. In un'istruzione $select è possibile usare solo i campi contrassegnati come Recuperabile.

Filtrare, facet e ordinare campi complessi

La stessa sintassi del percorso OData usata per i filtri e le ricerche a campi può essere usata anche per facet, ordinamento e selezione dei campi in una richiesta di ricerca. Per i tipi complessi, le regole applicano che regolano quali sottocampi possono essere contrassegnati come ordinabili o visualizzabili. Per altre informazioni su queste regole, vedere Le informazioni di riferimento sull'API Di creazione dell'indice.

Sottocampi in facet

Qualsiasi sottocampo può essere contrassegnato come facetable a meno che non sia di tipo Edm.GeographyPoint o Collection(Edm.GeographyPoint).

I conteggi dei documenti restituiti nei risultati del facet vengono calcolati per il documento padre (un hotel), non i documenti secondari in una raccolta complessa (sale). Si supponga, ad esempio, che un hotel abbia 20 camere di tipo "suite". Dato questo parametro facet=Rooms/Typefacet , il numero di facet è uno per l'hotel, non 20 per le camere.

Ordinamento di campi complessi

Le operazioni di ordinamento si applicano ai documenti (Hotel) e non ai documenti secondari (Rooms). Quando si dispone di una raccolta di tipi complessa, ad esempio Rooms, è importante tenere presente che non è possibile ordinare affatto Rooms. In effetti, non è possibile ordinare alcuna raccolta.

Le operazioni di ordinamento funzionano quando i campi hanno un singolo valore per ogni documento, indipendentemente dal fatto che il campo sia un campo semplice o un sottocampo in un tipo complesso. Ad esempio, Address/City può essere ordinato perché esiste un solo indirizzo per hotel, quindi $orderby=Address/City ordina gli hotel in base alla città.

Applicazione di filtri a campi complessi

È possibile fare riferimento a sottocampi di un campo complesso in un'espressione di filtro. È sufficiente usare la stessa sintassi del percorso OData usata per l'ordinamento, l'ordinamento e la selezione dei campi. Ad esempio, il filtro seguente restituisce tutti gli hotel in Canada:

$filter=Address/Country eq 'Canada'

Per filtrare in base a un campo di raccolta complesso, è possibile usare un'espressione lambda con glianyoperatori e all . In tal caso, la variabile di intervallo dell'espressione lambda è un oggetto con campi secondari. È possibile fare riferimento a tali campi secondari con la sintassi del percorso OData standard. Ad esempio, il filtro seguente restituisce tutti gli hotel con almeno una camera deluxe e tutte le camere non fumose:

$filter=Rooms/any(room: room/Type eq 'Deluxe Room') and Rooms/all(room: not room/SmokingAllowed)

Come per i campi semplici di primo livello, i campi secondari semplici di campi complessi possono essere inclusi solo nei filtri se l'attributo filtrabile è impostato su true nella definizione dell'indice. Per altre informazioni, vedere Le informazioni di riferimento sull'API Di creazione dell'indice.

Passaggi successivi

Provare il set di dati Hotels nella procedura guidata Importa dati . Per accedere ai dati, sono necessarie le informazioni di connessione di Azure Cosmos DB fornite nel file leggimi.

Con queste informazioni, il primo passaggio della procedura guidata consiste nel creare una nuova origine dati di Azure Cosmos DB. Più avanti nella procedura guidata, quando si arriva alla pagina dell'indice di destinazione, viene visualizzato un indice con tipi complessi. Creare e caricare questo indice e quindi eseguire query per comprendere la nuova struttura.