Condividi tramite


Proprietà calcolate in Azure Cosmos DB per NoSQL (anteprima)

SI APPLICA A: NoSQL

Le proprietà calcolate in Azure Cosmos DB hanno valori derivati dalle proprietà degli elementi esistenti, ma le proprietà non vengono rese persistenti negli elementi stessi. Le proprietà calcolate hanno come ambito un singolo elemento e possono essere referenziate nelle query come se fossero proprietà persistenti. Le proprietà calcolate semplificano la scrittura di una logica di query complessa una sola volta e la fanno riferimento più volte. È possibile aggiungere un singolo indice in queste proprietà o usarli come parte di un indice composito per migliorare le prestazioni.

Nota

Sono disponibili commenti e suggerimenti sulle proprietà calcolate? Saremo lieti di riceverli. È possibile condividere i feedback direttamente con il team di progettazione di Azure Cosmos DB: cosmoscomputedprops@microsoft.com.

Che cos'è una proprietà calcolata?

Le proprietà calcolate devono essere al livello superiore dell'elemento e non possono avere un percorso annidato. Ogni definizione di proprietà calcolata ha due componenti: un nome e una query. Il nome è il nome della proprietà calcolata e la query definisce la logica per calcolare il valore della proprietà per ogni elemento. Le proprietà calcolate hanno come ambito un singolo elemento e pertanto non possono usare valori di più elementi o basarsi su altre proprietà calcolate. Ogni contenitore può avere un massimo di 20 proprietà calcolate.

Definizione di proprietà calcolata di esempio:

{
  "computedProperties": [
    {
      "name": "cp_lowerName",
      "query": "SELECT VALUE LOWER(c.name) FROM c"
    }
  ]
}

Vincoli dei nomi

È consigliabile assegnare un nome alle proprietà calcolate in modo che non si verifichi un conflitto con un nome di proprietà persistente. Per evitare la sovrapposizione dei nomi di proprietà, è possibile aggiungere un prefisso o un suffisso a tutti i nomi di proprietà calcolati. Questo articolo usa il prefisso cp_ in tutte le definizioni dei nomi.

Importante

La definizione di una proprietà calcolata usando lo stesso nome di una proprietà persistente non genera un errore, ma potrebbe causare un comportamento imprevisto. Indipendentemente dal fatto che la proprietà calcolata sia indicizzata o meno, i valori delle proprietà persistenti che condividono un nome con una proprietà calcolata non verranno inclusi nell'indice. Le query useranno sempre la proprietà calcolata anziché la proprietà persistente, ad eccezione della proprietà persistente restituita anziché della proprietà calcolata se è presente una proiezione con caratteri jolly nella clausola SELECT. La proiezione con caratteri jolly non include automaticamente le proprietà calcolate.

I vincoli sui nomi delle proprietà calcolate sono:

  • Tutte le proprietà calcolate devono avere nomi univoci.
  • Il valore della proprietà rappresenta il nome della name proprietà di primo livello che può essere utilizzato per fare riferimento alla proprietà calcolata.
  • I nomi delle proprietà di sistema riservati, ad idesempio , _ride _ts non possono essere usati come nomi di proprietà calcolati.
  • Un nome di proprietà calcolata non può corrispondere a un percorso di proprietà già indicizzato. Questo vincolo si applica a tutti i percorsi di indicizzazione specificati, tra cui:
    • Percorsi inclusi
    • Percorsi esclusi
    • Indici spaziali
    • Indici compositi

Vincoli di query

Le query nella definizione della proprietà calcolata devono essere sintatticamente valide e semanticamente. In caso contrario, l'operazione di creazione o aggiornamento non riesce. Le query devono restituire un valore deterministico per tutti gli elementi in un contenitore. Le query possono restituire valori non definiti o Null per alcuni elementi e le proprietà calcolate con valori non definiti o Null si comportano come le proprietà persistenti con valori non definiti o Null quando vengono usate nelle query.

Le limitazioni relative alle definizioni di query delle proprietà calcolate sono:

  • Le query devono specificare una clausola FROM che rappresenta il riferimento all'elemento radice. Esempi di clausole FROM supportate sono: FROM c, FROM root ce FROM MyContainer c.
  • Le query devono usare una clausola VALUE nella proiezione.
  • Le query non possono includere join.
  • Le query non possono usare espressioni scalari non deterministiche. Esempi di espressioni scalari non deterministiche sono: GetCurrentDateTime, GetCurrentTimeStamp, GetCurrentTicks e RAND.
  • Le query non possono usare alcuna delle clausole seguenti: WHERE, GROUP BY, ORDER BY, TOP, DISTINCT, OFFSET LIMIT, EXISTS, ALL, LAST, FIRST e NONE.
  • Le query non possono includere una sottoquery scalare.
  • Le funzioni di aggregazione, le funzioni spaziali, le funzioni non deterministiche e le funzioni definite dall'utente non sono supportate.

Creare proprietà calcolate

Durante l'anteprima, le proprietà calcolate devono essere create usando .NET v3 o Java v4 SDK. Dopo aver creato le proprietà calcolate, è possibile eseguire query che fanno riferimento alle proprietà usando qualsiasi metodo, inclusi tutti gli SDK e Azure Esplora dati nella portale di Azure.

Versione supportata Note
.NET SDK v3 >= 3.34.0-preview Le proprietà calcolate sono attualmente disponibili solo nelle versioni di anteprima del pacchetto.
Java SDK v4 >= 4.46.0 Le proprietà calcolate sono attualmente in versione di anteprima.
Python SDK >= v4.5.2b5 Le proprietà calcolate sono attualmente in versione di anteprima.

Creare proprietà calcolate usando l'SDK

È possibile creare un nuovo contenitore con proprietà calcolate definite oppure aggiungere proprietà calcolate a un contenitore esistente.

Ecco un esempio di come creare proprietà calcolate in un nuovo contenitore:

ContainerProperties containerProperties = new ContainerProperties("myContainer", "/pk")
{
    ComputedProperties = new Collection<ComputedProperty>
    {
        new ComputedProperty
        {
            Name = "cp_lowerName",
            Query = "SELECT VALUE LOWER(c.name) FROM c"
        }
    }
};

Container container = await client.GetDatabase("myDatabase").CreateContainerAsync(containerProperties);

Ecco un esempio di come aggiornare le proprietà calcolate in un contenitore esistente:

var container = client.GetDatabase("myDatabase").GetContainer("myContainer");

// Read the current container properties
var containerProperties = await container.ReadContainerAsync();
// Make the necessary updates to the container properties
containerProperties.Resource.ComputedProperties = new Collection<ComputedProperty>
    {
        new ComputedProperty
        {
            Name = "cp_lowerName",
            Query = "SELECT VALUE LOWER(c.name) FROM c"
        },
        new ComputedProperty
        {
            Name = "cp_upperName",
            Query = "SELECT VALUE UPPER(c.name) FROM c"
        }
    };
// Update the container with changes
await container.ReplaceContainerAsync(containerProperties);

Suggerimento

Ogni volta che si aggiornano le proprietà del contenitore, i valori precedenti vengono sovrascritti. Se sono presenti proprietà calcolate esistenti e si desidera aggiungerne di nuove, assicurarsi di aggiungere proprietà calcolate nuove e esistenti alla raccolta.

Usare le proprietà calcolate nelle query

È possibile fare riferimento alle proprietà calcolate nelle query nello stesso modo in cui si fa riferimento alle proprietà persistenti. I valori per le proprietà calcolate non indicizzate vengono valutati durante il runtime usando la definizione della proprietà calcolata. Se viene indicizzata una proprietà calcolata, l'indice viene usato allo stesso modo usato per le proprietà persistenti e la proprietà calcolata viene valutata in base alle esigenze. È consigliabile aggiungere indici sulle proprietà calcolate per ottenere prestazioni e costi ottimali.

Gli esempi seguenti usano il set di dati dei prodotti di avvio rapido disponibile in Esplora dati nella portale di Azure. Per iniziare, selezionare Avvia l'avvio rapido e caricare il set di dati in un nuovo contenitore.

Screenshot che mostra come iniziare la guida introduttiva per caricare un set di dati di esempio nella portale di Azure.

Ecco un esempio di elemento:

{
  "id": "08225A9E-F2B3-4FA3-AB08-8C70ADD6C3C2",
  "categoryId": "75BF1ACB-168D-469C-9AA3-1FD26BB4EA4C",
  "categoryName": "Bikes, Touring Bikes",
  "sku": "BK-T79U-50",
  "name": "Touring-1000 Blue, 50",
  "description": "The product called \"Touring-1000 Blue, 50\"",
  "price": 2384.07,
  "tags": [
    {
      "id": "27B7F8D5-1009-45B8-88F5-41008A0F0393",
      "name": "Tag-61"
    }
  ],
  "_rid": "n7AmAPTJ480GAAAAAAAAAA==",
  "_self": "dbs/n7AmAA==/colls/n7AmAPTJ480=/docs/n7AmAPTJ480GAAAAAAAAAA==/",
  "_etag": "\"01002683-0000-0800-0000-6451fb4b0000\"",
  "_attachments": "attachments/",
  "_ts": 1683094347
}

Projection

Se è necessario proiettare le proprietà calcolate, è necessario farvi riferimento in modo esplicito. Le proiezioni con caratteri jolly come SELECT * restituiscono tutte le proprietà persistenti, ma non includono proprietà calcolate.

Ecco un esempio di definizione di proprietà calcolata per convertire la name proprietà in lettere minuscole:

{ 
  "name": "cp_lowerName", 
  "query": "SELECT VALUE LOWER(c.name) FROM c" 
} 

Questa proprietà può quindi essere proiettata in una query:

SELECT 
    c.cp_lowerName 
FROM 
    c

Clausola WHERE

È possibile fare riferimento alle proprietà calcolate nei predicati di filtro come qualsiasi proprietà persistente. È consigliabile aggiungere qualsiasi indice singolo o composito pertinente quando si usano le proprietà calcolate nei filtri.

Ecco un esempio di definizione di proprietà calcolata per calcolare uno sconto del prezzo del 20%:

{ 
  "name": "cp_20PercentDiscount", 
  "query": "SELECT VALUE (c.price * 0.2) FROM c" 
} 

Questa proprietà potrebbe quindi essere filtrata per garantire che vengano restituiti solo i prodotti in cui lo sconto sarebbe inferiore a $ 50:

SELECT 
    c.price - c.cp_20PercentDiscount as discountedPrice, 
    c.name 
FROM 
    c 
WHERE 
    c.cp_20PercentDiscount < 50.00

Clausola GROUP BY

Come per le proprietà persistenti, è possibile fare riferimento alle proprietà calcolate nella clausola GROUP BY e usare l'indice quando possibile. Per ottenere prestazioni ottimali, aggiungere qualsiasi indice singolo o composito pertinente.

Ecco un esempio di definizione di proprietà calcolata che trova la categoria primaria per ogni elemento della categoryName proprietà :

{
  "name": "cp_primaryCategory",
  "query": "SELECT VALUE SUBSTRING(c.categoryName, 0, INDEX_OF(c.categoryName, ',')) FROM c"
}

È quindi possibile raggruppare per cp_primaryCategory ottenere il numero di elementi in ogni categoria primaria:

SELECT 
    COUNT(1), 
    c.cp_primaryCategory 
FROM 
    c 
GROUP BY 
    c.cp_primaryCategory

Suggerimento

Anche se è possibile ottenere questa query anche senza usare le proprietà calcolate, l'uso delle proprietà calcolate semplifica notevolmente la scrittura della query e consente un miglioramento delle prestazioni perché cp_primaryCategory può essere indicizzato. Sia SUBSTRING() che INDEX_OF() richiedono un'analisi completa di tutti gli elementi nel contenitore, ma se si indicizza la proprietà calcolata, l'intera query può essere servita dall'indice. La possibilità di gestire la query dall'indice invece di basarsi su un'analisi completa aumenta le prestazioni e riduce i costi dell'unità richiesta di query (UR).

Clausola ORDER BY

Come per le proprietà persistenti, è possibile fare riferimento alle proprietà calcolate nella clausola ORDER BY e devono essere indicizzate affinché la query abbia esito positivo. Usando le proprietà calcolate, è possibile ORDINARE BY il risultato di una logica complessa o di funzioni di sistema, che apre molti nuovi scenari di query quando si usa Azure Cosmos DB.

Ecco un esempio di definizione di proprietà calcolata che ottiene il mese fuori dal _ts valore:

{
  "name": "cp_monthUpdated",
  "query": "SELECT VALUE DateTimePart('m', TimestampToDateTime(c._ts*1000)) FROM c"
}

Prima di poter ordinare BY cp_monthUpdated, è necessario aggiungerlo ai criteri di indicizzazione. Dopo aver aggiornato i criteri di indicizzazione, è possibile ordinare in base alla proprietà calcolata.

SELECT
    *
FROM
    c
ORDER BY
    c.cp_monthUpdated

Proprietà calcolate dell'indice

Le proprietà calcolate non vengono indicizzate per impostazione predefinita e non sono coperte dai percorsi con caratteri jolly nei criteri di indicizzazione. È possibile aggiungere indici singoli o compositi in proprietà calcolate nei criteri di indicizzazione allo stesso modo in cui si aggiungerebbero indici in proprietà persistenti. È consigliabile aggiungere indici pertinenti a tutte le proprietà calcolate. È consigliabile usare questi indici perché sono utili per aumentare le prestazioni e ridurre le UR quando vengono indicizzate. Quando le proprietà calcolate vengono indicizzate, i valori effettivi vengono valutati durante le operazioni di scrittura degli elementi per generare e rendere persistenti i termini di indice.

Esistono alcune considerazioni per l'indicizzazione delle proprietà calcolate, tra cui:

  • Le proprietà calcolate possono essere specificate in percorsi inclusi, percorsi esclusi e percorsi di indice compositi.
  • Le proprietà calcolate non possono avere un indice spaziale definito su di essi.
  • I percorsi con caratteri jolly nel percorso della proprietà calcolata funzionano come per le proprietà normali.
  • Se si rimuove una proprietà calcolata indicizzata, è necessario eliminare anche tutti gli indici di tale proprietà.

Nota

Tutte le proprietà calcolate vengono definite al livello superiore dell'elemento. Il percorso è sempre /<computed property name>.

Suggerimento

Ogni volta che si aggiornano le proprietà del contenitore, i valori precedenti vengono sovrascritti. Se sono presenti proprietà calcolate esistenti e si desidera aggiungerne di nuove, assicurarsi di aggiungere proprietà calcolate nuove e esistenti alla raccolta.

Nota

Quando la definizione di una proprietà calcolata indicizzata viene modificata, non viene reindicizzazione automatica. Per indicizzare la proprietà calcolata modificata, è prima necessario eliminare la proprietà calcolata dall'indice. Dopo aver completato la reindicizzazione, aggiungere di nuovo la proprietà calcolata ai criteri di indice.

Se si vuole eliminare una proprietà calcolata, è prima necessario rimuoverla dai criteri di indice.

Aggiungere un singolo indice per le proprietà calcolate

Per aggiungere un singolo indice per una proprietà calcolata denominata cp_myComputedProperty:

{
  "indexingMode": "consistent",
  "automatic": true,
  "includedPaths": [
    {
      "path": "/*"
    },
    {
      "path": "/cp_myComputedProperty/?"
    }
  ],
  "excludedPaths": [
    {
      "path": "/\"_etag\"/?"
    }
  ]
}

Aggiungere un indice composito per le proprietà calcolate

Per aggiungere un indice composito in due proprietà in cui, uno viene calcolato come e l'altro viene salvato in modo permanente come cp_myComputedPropertymyPersistedProperty:

{
  "indexingMode": "consistent",
  "automatic": true,
  "includedPaths": [
    {
      "path": "/*"
    }
  ],
  "excludedPaths": [
    {
      "path": "/\"_etag\"/?"
    }
  ],
  "compositeIndexes": [
    [
      {
        "path": "/cp_myComputedProperty"
      },
      {
        "path": "/path/to/myPersistedProperty"
      }
    ]
  ]
}

Informazioni sull'utilizzo delle unità richiesta

L'aggiunta di proprietà calcolate a un contenitore non usa unità richiesta. Le operazioni di scrittura sui contenitori con proprietà calcolate definite potrebbero comportare un lieve aumento delle UR. Se viene indicizzata una proprietà calcolata, le UR sulle operazioni di scrittura aumentano per riflettere i costi per l'indicizzazione e la valutazione della proprietà calcolata. Durante l'anteprima, gli addebiti delle UR correlati alle proprietà calcolate sono soggetti a modifiche.