Partilhar via


Propriedades computadas no Azure Cosmos DB para NoSQL

APLICA-SE A: NoSQL

As propriedades computadas no Azure Cosmos DB têm valores derivados de propriedades de item existentes, mas as propriedades não persistem nos próprios itens. As propriedades computadas têm como escopo um único item e podem ser referenciadas em consultas como se fossem propriedades persistentes. As propriedades computadas tornam mais fácil escrever lógica de consulta complexa uma vez e fazer referência a ela muitas vezes. Você pode adicionar um único índice nessas propriedades ou usá-los como parte de um índice composto para aumentar o desempenho.

Nota

Você tem algum feedback sobre as propriedades computadas? Queremos ouvi-lo! Sinta-se à vontade para compartilhar comentários diretamente com a equipe de engenharia do Azure Cosmos DB: cosmoscomputedprops@microsoft.com.

O que é uma propriedade calculada?

As propriedades computadas devem estar no nível superior do item e não podem ter um caminho aninhado. Cada definição de propriedade computada tem dois componentes: um nome e uma consulta. O nome é o nome da propriedade computada e a consulta define a lógica para calcular o valor da propriedade para cada item. As propriedades computadas têm como escopo um item individual e, portanto, não podem usar valores de vários itens ou depender de outras propriedades computadas. Cada recipiente pode ter um máximo de 20 propriedades computadas.

Exemplo de definição de propriedade computada:

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

Restrições de nome

É altamente recomendável que você nomeie propriedades computadas para que não haja colisão com um nome de propriedade persistente. Para evitar a sobreposição de nomes de propriedade, você pode adicionar um prefixo ou sufixo a todos os nomes de propriedade computados. Este artigo usa o prefixo cp_ em todas as definições de nome.

Importante

Definir uma propriedade computada usando o mesmo nome de uma propriedade persistente não resulta em um erro, mas pode levar a um comportamento inesperado. Independentemente de a propriedade calculada ser indexada, os valores das propriedades persistidas que partilham um nome com uma propriedade calculada não serão incluídos no índice. As consultas utilizarão sempre a propriedade calculada em vez da propriedade persistida, com a exceção de a propriedade persistida ser devolvida em vez da propriedade calculada se existir uma projeção de caráter universal na cláusula SELECT. A projeção curinga não inclui automaticamente propriedades computadas.

As restrições nos nomes de propriedade computados são:

  • Todas as propriedades computadas devem ter nomes exclusivos.
  • O valor da propriedade representa o name nome da propriedade de nível superior que pode ser usado para fazer referência à propriedade computada.
  • Nomes de propriedades do sistema reservados, como id, _ride _ts não podem ser usados como nomes de propriedades computadas.
  • Um nome de propriedade computado não pode corresponder a um caminho de propriedade que já está indexado. Essa restrição se aplica a todos os caminhos de indexação especificados, incluindo:
    • Caminhos incluídos
    • Caminhos excluídos
    • Índices espaciais
    • Índices compostos

Restrições de consulta

As consultas na definição de propriedade computada devem ser válidas sintaticamente e semanticamente, caso contrário, a operação de criação ou atualização falhará. As consultas devem ser avaliadas com um valor determinístico para todos os itens em um contêiner. As consultas podem ser avaliadas como indefinidas ou nulas para alguns itens, e as propriedades computadas com valores indefinidos ou nulos se comportam da mesma forma que as propriedades persistentes com valores indefinidos ou nulos quando usadas em consultas.

As limitações nas definições de consulta de propriedade computada são:

  • As consultas devem especificar uma cláusula FROM que represente a referência do item raiz. Exemplos de cláusulas FROM suportadas são: FROM c, FROM root c, e FROM MyContainer c.
  • As consultas devem usar uma cláusula VALUE na projeção.
  • As consultas não podem incluir um JOIN.
  • As consultas não podem usar expressões escalares não determinísticas. Exemplos de expressões escalares não determinísticas são: GetCurrentDateTime, GetCurrentTimeStamp, GetCurrentTicks e RAND.
  • As consultas não podem usar nenhuma das seguintes cláusulas: WHERE, GROUP BY, ORDER BY, TOP, DISTINCT, OFFSET LIMIT, EXISTS, ALL, LAST, FIRST e NONE.
  • As consultas não podem incluir uma subconsulta escalar.
  • Não há suporte para funções agregadas, funções espaciais, funções não determinísticas e funções definidas pelo usuário (UDFs).

Criar propriedades computadas

Depois que as propriedades computadas forem criadas, você poderá executar consultas que façam referência às propriedades usando qualquer método, incluindo todos os SDKs e o Azure Data Explorer no portal do Azure.

Versão suportada Notas
SDK do .NET v3 >= 3.34.0-visualização Atualmente, as propriedades computadas estão disponíveis apenas em versões de pacotes de visualização.
Java SDK v4 >= 4,46,0 As propriedades computadas estão atualmente na versão de visualização.
Python SDK >= v4.5.2b5 As propriedades computadas estão atualmente na versão de visualização.

Criar propriedades computadas usando o SDK

Você pode criar um novo contêiner que tenha propriedades computadas definidas ou adicionar propriedades computadas a um contêiner existente.

Veja um exemplo de como criar propriedades computadas em um novo contêiner:

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

Veja um exemplo de como atualizar propriedades computadas em um contêiner existente:

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

Gorjeta

Sempre que você atualiza as propriedades do contêiner, os valores antigos são substituídos. Se você tiver propriedades computadas existentes e quiser adicionar novas, certifique-se de adicionar propriedades computadas novas e existentes à coleção.

Usar propriedades computadas em consultas

As propriedades computadas podem ser referenciadas em consultas da mesma forma que as propriedades persistentes são referenciadas. Os valores para propriedades computadas que não são indexadas são avaliados durante o tempo de execução usando a definição de propriedade computada. Se uma propriedade computada for indexada, o índice será usado da mesma forma que é usado para propriedades persistentes, e a propriedade computada será avaliada conforme necessário. Recomendamos que você adicione índices em suas propriedades computadas para obter o melhor custo e desempenho.

Os exemplos a seguir usam o conjunto de dados de produtos de início rápido disponível no Data Explorer no portal do Azure. Para começar, selecione Iniciar o início rápido e carregue o conjunto de dados em um novo contêiner.

Captura de tela que mostra como iniciar o início rápido para carregar um conjunto de dados de exemplo no portal do Azure.

Aqui está um exemplo de um item:

{
  "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
}

Projeção

Se as propriedades computadas precisarem ser projetadas, elas devem ser explicitamente referenciadas. Projeções curinga como SELECT * retornar todas as propriedades persistentes, mas não incluem propriedades computadas.

Aqui está um exemplo de definição de propriedade computada para converter a name propriedade em minúsculas:

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

Essa propriedade pode então ser projetada em uma consulta:

SELECT 
    c.cp_lowerName 
FROM 
    c

Cláusula WHERE

As propriedades computadas podem ser referenciadas em predicados de filtro como quaisquer propriedades persistentes. Recomendamos que você adicione quaisquer índices únicos ou compostos relevantes ao usar propriedades computadas em filtros.

Veja um exemplo de definição de propriedade calculada para calcular um desconto de preço de 20%:

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

Esta propriedade pode então ser filtrada para garantir que apenas os produtos em que o desconto seria inferior a $50 são devolvidos:

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

Cláusula GROUP BY

Tal como acontece com as propriedades persistentes, as propriedades computadas podem ser referenciadas na cláusula GROUP BY e usar o índice sempre que possível. Para obter o melhor desempenho, adicione quaisquer índices únicos ou compostos relevantes.

Aqui está um exemplo de definição de propriedade computada que localiza a categoria primária para cada item da categoryName propriedade:

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

Em seguida, você pode agrupar por cp_primaryCategory para obter a contagem de itens em cada categoria primária:

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

Gorjeta

Embora você também possa realizar essa consulta sem usar propriedades computadas, usar as propriedades computadas simplifica muito a escrita da consulta e permite um maior desempenho porque cp_primaryCategory pode ser indexado. SUBSTRING () e INDEX_OF() exigem uma verificação completa de todos os itens no contêiner, mas se você indexar a propriedade computada, toda a consulta poderá ser servida a partir do índice. A capacidade de servir a consulta a partir do índice em vez de depender de uma verificação completa aumenta o desempenho e reduz os custos da unidade de solicitação de consulta (RU).

Cláusula ORDER BY

Assim como acontece com as propriedades persistentes, as propriedades computadas podem ser referenciadas na cláusula ORDER BY e devem ser indexadas para que a consulta seja bem-sucedida. Usando propriedades computadas, você pode ORDENAR POR o resultado de lógicas complexas ou funções do sistema, o que abre muitos novos cenários de consulta quando você usa o Azure Cosmos DB.

Aqui está um exemplo de definição de propriedade computada que obtém o _ts mês do valor:

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

Antes de poder ENCOMENDAR POR cp_monthUpdated, deve adicioná-lo à sua política de indexação. Depois que sua política de indexação for atualizada, você poderá solicitar pela propriedade computada.

SELECT
    *
FROM
    c
ORDER BY
    c.cp_monthUpdated

Propriedades calculadas do índice

As propriedades computadas não são indexadas por padrão e não são cobertas por caminhos curinga na política de indexação. Você pode adicionar índices únicos ou compostos em propriedades computadas na política de indexação da mesma forma que adicionaria índices em propriedades persistentes. Recomendamos que você adicione índices relevantes a todas as propriedades computadas. Recomendamos esses índices porque eles são benéficos para aumentar o desempenho e reduzir as RUs quando são indexados. Quando as propriedades calculadas são indexadas, os valores reais são avaliados durante as operações de gravação do item para gerar e persistir termos de índice.

Há algumas considerações para indexar propriedades computadas, incluindo:

  • As propriedades computadas podem ser especificadas em caminhos incluídos, caminhos excluídos e caminhos de índice composto.
  • As propriedades computadas não podem ter um índice espacial definido nelas.
  • Os caminhos curinga sob o caminho de propriedade computado funcionam como para propriedades regulares.
  • Se você estiver removendo uma propriedade computada que foi indexada, todos os índices nessa propriedade também deverão ser descartados.

Nota

Todas as propriedades computadas são definidas no nível superior do item. O caminho é sempre /<computed property name>.

Gorjeta

Sempre que você atualiza as propriedades do contêiner, os valores antigos são substituídos. Se você tiver propriedades computadas existentes e quiser adicionar novas, certifique-se de adicionar propriedades computadas novas e existentes à coleção.

Nota

Quando a definição de uma propriedade computada indexada é modificada, ela não é reindexada automaticamente. Para indexar a propriedade computada modificada, primeiro você precisará descartar a propriedade computada do índice. Depois que a reindexação for concluída, adicione a propriedade computada de volta à política de índice.

Se quiser excluir uma propriedade calculada, primeiro será necessário removê-la da política de índice.

Adicionar um único índice para propriedades computadas

Para adicionar um único índice para uma propriedade calculada chamada cp_myComputedProperty:

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

Adicionar um índice composto para propriedades computadas

Para adicionar um índice composto em duas propriedades nas quais, uma é calculada como cp_myComputedProperty, e a outra é persistida como myPersistedProperty:

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

Compreender o consumo unitário de pedido

Adicionar propriedades computadas a um contêiner não consome RUs. As operações de gravação em contêineres que têm propriedades computadas definidas podem ter um ligeiro aumento de RU. Se uma propriedade computada for indexada, as RUs em operações de gravação aumentarão para refletir os custos de indexação e avaliação da propriedade calculada.