Modellare tipi di dati complessi in Ricerca cognitiva di Azure

I set di dati esterni usati per popolare un indice di Ricerca cognitiva di Azure possono venire in molte forme. In alcuni casi includono sottostruttura gerarchica o annidata. 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 cognitiva di Azure usa per questo concetto è un tipo complesso. In Ricerca cognitiva di Azure i tipi complessi vengono modellati usando campi complessi. Un campo complesso è un campo che contiene elementi figlio (sottocampi) 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 cognitiva di Azure supporta in modo nativo tipi e raccolte complessi. Questi tipi consentono di modellare quasi tutte le strutture JSON in un indice di Ricerca cognitiva di Azure. Nelle versioni precedenti delle API di Ricerca cognitiva di Azure è possibile importare solo set di righe flat. 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, l'indice può avere anche tipi complessi.

Per iniziare, è consigliabile usare il set di dati Hotels, che è possibile caricare nella procedura guidata Importa dati nel 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 flat 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 una struttura complessa

Il documento JSON seguente è costituito da campi semplici e campi complessi. I campi complessi, ad esempio Address e Rooms, hanno campi secondari. Address dispone di un singolo set di valori per tali sotto campi, poiché si tratta di un singolo oggetto nel documento. Al contrario, Rooms dispone di più set di valori per i relativi campi secondari, uno per ogni oggetto nell'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 camera. 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 Tags).

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 esistente, 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 i campi complessi

Tutte le regole di reindicizzazione che si applicano ai campi in generale si applicano comunque a campi complessi. Se si riformulano 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 viene eseguita.

Aggiornamenti strutturali alla definizione

È possibile aggiungere nuovi sottocampi 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, 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 dei 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 lo stesso 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 sono presenti 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 una corrispondenza con due termini, "Portland" e "OR", in due sottocampi del campo Indirizzo:

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

Le query come questa non sono correlate alla ricerca full-text, a differenza dei filtri. Nei filtri, le query sui sotto campi 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à dell'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, vedere Informazioni sui filtri di raccolta OData in Ricerca cognitiva 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 che vengano visualizzati 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 campiate può essere usata anche per facet, ordinamento e selezione di campi in una richiesta di ricerca. Per i tipi complessi, le regole si applicano che regolano quali campi secondari possono essere contrassegnati come ordinabili o facetable. Per altre informazioni su queste regole, vedere le informazioni di riferimento sull'API Create Index.

Campi secondari in base al facet

Qualsiasi sottocampo può essere contrassegnato come tabella visibile 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 per i documenti secondari in una raccolta complessa (stanze). Si supponga, ad esempio, che un hotel abbia 20 camere di tipo "suite". Dato questo parametro facet=Rooms/Typefacet , il conteggio dei facet sarà uno per l'hotel, non 20 per le camere.

Ordinamento di campi complessi

Le operazioni di ordinamento si applicano ai documenti (Alberghi) e non ai documenti secondari (Camere). Quando si dispone di una raccolta di tipi complessi, ad esempio Rooms, è importante capire che non è possibile ordinare su Rooms. Infatti, non è possibile ordinare alcuna raccolta.

Le operazioni di ordinamento funzionano quando i campi hanno un singolo valore per documento, indipendentemente dal fatto che il campo sia un campo semplice o un sottocampo in un tipo complesso. Ad esempio, Address/City è consentito l'ordinamento perché è presente un solo indirizzo per hotel, quindi $orderby=Address/City ordinare gli hotel in base alla città.

Filtro su campi complessi

È possibile fare riferimento ai sottocampi di un campo complesso in un'espressione di filtro. Usare la stessa sintassi del percorso OData usata per facet, ordinamento e selezione di campi. Ad esempio, il filtro seguente restituirà tutti gli hotel in Canada:

$filter=Address/Country eq 'Canada'

Per filtrare in un campo di raccolta complesso, è possibile usare un'espressione lambda con gli any operatori eall. 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 restituirà tutti gli hotel con almeno una camera deluxe e tutte le camere non fumatori:

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

Come nei campi semplici di primo livello, i campi secondari semplici di campi complessi possono essere inclusi solo nei filtri se hanno l'attributo filtrabile impostato su true nella definizione dell'indice. Per altre informazioni, vedere Il riferimento all'API Crea indice.

Passaggi successivi

Provare il set di dati Hotels nella procedura guidata Importa dati . Sono necessarie le informazioni di connessione di Cosmos DB fornite nel readme per accedere ai dati.

Con queste informazioni in mano, 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, verrà visualizzato un indice con tipi complessi. Creare e caricare questo indice e quindi eseguire query per comprendere la nuova struttura.