Dela via


Beräknade egenskaper i Azure Cosmos DB för NoSQL

GÄLLER FÖR: NoSQL

Beräknade egenskaper i Azure Cosmos DB har värden som härleds från befintliga objektegenskaper, men egenskaperna sparas inte i själva objekten. Beräknade egenskaper är begränsade till ett enskilt objekt och kan refereras i frågor som om de vore bevarade egenskaper. Beräknade egenskaper gör det enklare att skriva komplex frågelogik en gång och referera till den många gånger. Du kan lägga till ett enda index för dessa egenskaper eller använda dem som en del av ett sammansatt index för ökad prestanda.

Kommentar

Har du någon feedback om beräknade egenskaper? Vi vill höra det! Dela gärna feedback direkt med Azure Cosmos DB:s utvecklingsteam: cosmoscomputedprops@microsoft.com.

Vad är en beräknad egenskap?

Beräknade egenskaper måste vara på den översta nivån i objektet och kan inte ha en kapslad sökväg. Varje beräknad egenskapsdefinition har två komponenter: ett namn och en fråga. Namnet är det beräknade egenskapsnamnet och frågan definierar logik för att beräkna egenskapsvärdet för varje objekt. Beräknade egenskaper är begränsade till ett enskilt objekt och kan därför inte använda värden från flera objekt eller förlita sig på andra beräknade egenskaper. Varje container kan ha högst 20 beräknade egenskaper.

Exempel på beräkningsegenskapsdefinition:

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

Namnbegränsningar

Vi rekommenderar starkt att du namnger beräknade egenskaper så att det inte uppstår någon kollision med ett beständiga egenskapsnamn. För att undvika överlappande egenskapsnamn kan du lägga till ett prefix eller suffix i alla beräknade egenskapsnamn. Den här artikeln använder prefixet cp_ i alla namndefinitioner.

Viktigt!

Att definiera en beräknad egenskap med samma namn som en bevarad egenskap resulterar inte i ett fel, men det kan leda till oväntat beteende. Oavsett om den beräknade egenskapen är indexerad inkluderas inte värden från bestående egenskaper som delar namn med en beräknad egenskap i indexet. Frågor använder alltid den beräknade egenskapen i stället för den bestående egenskapen, med undantag för att den bestående egenskapen returneras i stället för den beräknade egenskapen om det finns en jokerteckenprojektion i SELECT-satsen. Jokerteckenprojektion innehåller inte automatiskt beräknade egenskaper.

Begränsningarna för beräknade egenskapsnamn är:

  • Alla beräknade egenskaper måste ha unika namn.
  • Värdet för name egenskapen representerar det egenskapsnamn på den översta nivån som kan användas för att referera till den beräknade egenskapen.
  • Reserverade systemegenskapsnamn som id, _ridoch _ts kan inte användas som beräknade egenskapsnamn.
  • Ett beräknat egenskapsnamn kan inte matcha en egenskapssökväg som redan är indexerad. Den här begränsningen gäller för alla indexeringssökvägar som anges, inklusive:
    • Inkluderade sökvägar
    • Undantagna sökvägar
    • Rumsliga index
    • Sammansatta index

Frågebegränsningar

Frågor i den beräknade egenskapsdefinitionen måste vara giltiga syntaktiskt och semantiskt, annars misslyckas åtgärden för att skapa eller uppdatera. Frågor bör utvärderas till ett deterministiskt värde för alla objekt i en container. Frågor kan utvärderas till odefinierat eller null för vissa objekt, och beräknade egenskaper med odefinierade värden eller nullvärden fungerar på samma sätt som bevarade egenskaper med odefinierade värden eller nullvärden när de används i frågor.

Begränsningarna för frågedefinitioner för beräknade egenskaper är:

  • Frågor måste ange en FROM-sats som representerar rotobjektets referens. Exempel på FROM-satser som stöds är: FROM c, FROM root coch FROM MyContainer c.
  • Frågor måste använda en VALUE-sats i projektionen.
  • Frågor kan inte innehålla en JOIN.
  • Frågor kan inte använda icke-terministiska scalar-uttryck. Exempel på icke-terministiska skaläruttryck är: GetCurrentDateTime, GetCurrentTimeStamp, GetCurrentTicks och RAND.
  • Frågor kan inte använda någon av följande satser: WHERE, GROUP BY, ORDER BY, TOP, DISTINCT, OFFSET LIMIT, EXISTS, ALL, LAST, FIRST och NONE.
  • Frågor kan inte innehålla en skalär underfråga.
  • Aggregeringsfunktioner, rumsliga funktioner, icke-terministiska funktioner och användardefinierade funktioner (UDF: er) stöds inte.

Skapa beräknade egenskaper

När de beräknade egenskaperna har skapats kan du köra frågor som refererar till egenskaperna med valfri metod, inklusive alla programutvecklingspaket (SDK:er) och Azure Data Explorer i Azure-portalen.

Version som stöds Kommentar
.NET SDK v3 >= 3.34.0-preview Beräknade egenskaper är för närvarande endast tillgängliga i förhandsversioner av paket.
Java SDK v4 >= 4.46.0 Beräknade egenskaper är för närvarande under förhandsversion.
Python SDK >= v4.5.2b5 Beräknade egenskaper är för närvarande under förhandsversion.

Skapa beräknade egenskaper med hjälp av SDK

Du kan antingen skapa en ny container som har definierade egenskaper eller lägga till beräknade egenskaper i en befintlig container.

Här är ett exempel på hur du skapar beräknade egenskaper i en ny container:

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);

Här är ett exempel på hur du uppdaterar beräknade egenskaper i en befintlig container:

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);

Dricks

Varje gång du uppdaterar containeregenskaper skrivs de gamla värdena över. Om du har befintliga beräknade egenskaper och vill lägga till nya ska du lägga till både nya och befintliga beräknade egenskaper i samlingen.

Skapa beräknade egenskaper med hjälp av Datautforskaren

Du kan använda Datautforskaren för att skapa en beräknad egenskap för en container.

  1. Öppna din befintliga container i Datautforskaren.

  2. Gå till avsnittet Inställningar för containern. Navigera sedan till underavsnittet *Beräknade egenskaper .

  3. Redigera JSON för den beräknade egenskapsdefinitionen för containern. I det här exemplet används den här JSON:en för att definiera en beräknad egenskap för att dela upp strängen SKU för en detaljhandelsprodukt med avgränsaren - .

    [
      {
        "name": "cp_splitSku",
        "query": "SELECT VALUE StringSplit(p.sku, \"-\") FROM products p"
      }
    ]
    

    Skärmbild av JSON-redigeraren för beräknade egenskaper i datautforskarens gränssnitt.

  4. Spara den beräknade egenskapen.

Använda beräknade egenskaper i frågor

Beräknade egenskaper kan refereras till i frågor på samma sätt som beständiga egenskaper refereras till. Värden för beräknade egenskaper som inte indexeras utvärderas under körningen med hjälp av den beräknade egenskapsdefinitionen. Om en beräknad egenskap indexeras används indexet på samma sätt som det används för bevarade egenskaper och den beräknade egenskapen utvärderas efter behov. Vi rekommenderar att du lägger till index för dina beräknade egenskaper för bästa kostnad och prestanda.

I följande exempel används den datauppsättning för snabbstartsprodukter som är tillgänglig i Datautforskaren i Azure-portalen. Kom igång genom att välja Starta snabbstarten och läsa in datamängden i en ny container.

Skärmbild som illustrerar hur du läser in en exempeldatauppsättning i en databas och container.

Här är ett exempel på ett objekt:

{
  "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
  "categoryId": "bbbbbbbb-1111-2222-3333-cccccccccccc",
  "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": "cccccccc-2222-3333-4444-dddddddddddd",
      "name": "Tag-61"
    }
  ],
  "_rid": "n7AmAPTJ480GAAAAAAAAAA==",
  "_self": "dbs/n7AmAA==/colls/n7AmAPTJ480=/docs/n7AmAPTJ480GAAAAAAAAAA==/",
  "_etag": "\"01002683-0000-0800-0000-6451fb4b0000\"",
  "_attachments": "attachments/",
  "_ts": 1683094347
}

Projektion

Om beräknade egenskaper måste projiceras måste de uttryckligen refereras till. Jokerteckenprojektioner som SELECT * returnerar alla bevarade egenskaper, men de innehåller inte beräknade egenskaper.

Här är ett exempel på en beräknad egenskapsdefinition för att konvertera egenskapen till gemener name :

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

Den här egenskapen kan sedan projiceras i en fråga:

SELECT 
    c.cp_lowerName 
FROM 
    c

WHERE-satsen

Beräknade egenskaper kan refereras till i filterpredikat som alla beständiga egenskaper. Vi rekommenderar att du lägger till relevanta enskilda eller sammansatta index när du använder beräknade egenskaper i filter.

Här är ett exempel på en beräknad egenskapsdefinition för att beräkna en prisrabatt på 20 procent:

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

Den här egenskapen kan sedan filtreras på för att säkerställa att endast produkter där rabatten skulle vara mindre än 50 USD returneras:

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

GROUP BY-sats

Precis som med bevarade egenskaper kan beräknade egenskaper refereras till i GROUP BY-satsen och använda indexet när det är möjligt. För bästa prestanda lägger du till relevanta enskilda eller sammansatta index.

Här är ett exempel på en beräknad egenskapsdefinition som hittar den primära kategorin för varje objekt från categoryName egenskapen:

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

Du kan sedan gruppera cp_primaryCategory efter för att få antalet objekt i varje primär kategori:

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

Dricks

Även om du också kan uppnå den här frågan utan att använda beräknade egenskaper, förenklar användningen av de beräknade egenskaperna avsevärt att skriva frågan och ger bättre prestanda eftersom cp_primaryCategory kan indexeras. Både SUBSTRING() och INDEX_OF() kräver en fullständig genomsökning av alla objekt i containern, men om du indexerar den beräknade egenskapen kan hela frågan hanteras från indexet i stället. Möjligheten att hantera frågan från indexet i stället för att förlita sig på en fullständig genomsökning ökar prestandan och sänker ru-kostnaderna (query request unit).

ORDER BY-satsen

Precis som med bevarade egenskaper kan beräknade egenskaper refereras till i ORDER BY-satsen och de måste indexeras för att frågan ska lyckas. Genom att använda beräknade egenskaper kan du BESTÄLLA EFTER resultatet av komplexa logik- eller systemfunktioner, vilket öppnar upp många nya frågescenarier när du använder Azure Cosmos DB.

Här är ett exempel på en beräknad egenskapsdefinition som hämtar månaden från _ts värdet:

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

Innan du kan BESTÄLLA EFTER cp_monthUpdatedmåste du lägga till den i indexeringsprincipen. När indexeringsprincipen har uppdaterats kan du beställa efter den beräknade egenskapen.

SELECT
    *
FROM
    c
ORDER BY
    c.cp_monthUpdated

Indexberäknade egenskaper

Beräknade egenskaper indexeras inte som standard och omfattas inte av sökvägar med jokertecken i indexeringsprincipen. Du kan lägga till enskilda eller sammansatta index på beräknade egenskaper i indexeringsprincipen på samma sätt som du lägger till index för bevarade egenskaper. Vi rekommenderar att du lägger till relevanta index i alla beräknade egenskaper. Vi rekommenderar dessa index eftersom de är bra när det gäller att öka prestanda och minska enheter för begäranden (RU:er). När beräknade egenskaper indexeras utvärderas faktiska värden under objektskrivningsåtgärder för att generera och bevara indexvillkor.

Det finns några saker att tänka på när du indexerar beräknade egenskaper, bland annat:

  • Beräknade egenskaper kan anges i inkluderade sökvägar, exkluderade sökvägar och sammansatta indexsökvägar
  • Beräknade egenskaper kan inte ha ett rumsligt index definierat på dem
  • Sökvägar med jokertecken under den beräknade egenskapssökvägen fungerar som de gör för vanliga egenskaper
  • Relaterade index på en borttagen och indexerad egenskap måste också tas bort

Kommentar

Alla beräknade egenskaper definieras på objektets översta nivå. Sökvägen är alltid /<computed property name>.

Dricks

Varje gång du uppdaterar containeregenskaper skrivs de gamla värdena över. Om du har befintliga beräknade egenskaper och vill lägga till nya ska du lägga till både nya och befintliga beräknade egenskaper i samlingen.

Kommentar

När definitionen av en indexerad beräknad egenskap ändras, indexeras den inte automatiskt om. Om du vill indexeras den ändrade beräknade egenskapen måste du först ta bort den beräknade egenskapen från indexet. När omindexeringen har slutförts lägger du sedan till den beräknade egenskapen i indexprincipen igen.

Om du vill ta bort en beräknad egenskap måste du först ta bort den från indexprincipen.

Lägga till ett enda index för beräknade egenskaper

Så här lägger du till ett enda index för en beräknad egenskap med namnet cp_myComputedProperty:

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

Lägga till ett sammansatt index för beräknade egenskaper

Om du vill lägga till ett sammansatt index för två egenskaper som beräknas som cp_myComputedProperty, och det andra sparas som myPersistedProperty:

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

Förstå enhetsförbrukning för begäranden

Att lägga till beräknade egenskaper i en container förbrukar inte RU:er. Skrivåtgärder på containrar med definierade beräknade egenskaper kan ha en liten RU-ökning. Om en beräknad egenskap indexeras ökar RU:er för skrivåtgärder för att återspegla kostnaderna för indexering och utvärdering av den beräknade egenskapen.