Partager via


Propriétés calculées dans Azure Cosmos DB pour NoSQL

S’APPLIQUE À : NoSQL

Les propriétés calculées dans Azure Cosmos DB ont des valeurs dérivées des propriétés d’élément existantes, mais ne sont pas conservées dans les éléments eux-mêmes. Les propriétés calculées sont limitées à un seul élément et peuvent être référencées dans des requêtes comme s’il s’agissait de propriétés persistantes. Les propriétés calculées facilitent l'écriture d'une logique d'interrogation complexe une fois pour la référencer plusieurs fois. Vous pouvez ajouter un index unique à ces propriétés ou les utiliser dans le cadre d’un index composite pour améliorer les performances.

Notes

Avez-vous des commentaires sur les propriétés calculées ? Nous attendons vos remarques ! N’hésitez pas à partager vos commentaires directement avec l’équipe d’ingénieurs Azure Cosmos DB : cosmoscomputedprops@microsoft.com.

Qu’est-ce qu’une propriété calculée ?

Les propriétés calculées doivent se trouver au niveau supérieur de l’élément et ne peuvent pas avoir de chemin imbriqué. Chaque définition de propriété calculée a deux composants : un nom et une requête. Le nom est le nom de la propriété calculée, et la requête définit la logique pour calculer la valeur de la propriété pour chaque élément. Les propriétés calculées sont limitées à un élément individuel et ne peuvent donc pas utiliser les valeurs de plusieurs éléments ou s’appuyer sur d’autres propriétés calculées. Chaque conteneur peut avoir un maximum de 20 propriétés calculées.

Exemple de définition de propriété calculée :

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

Contraintes de nom

Nous vous recommandons vivement de nommer les propriétés calculées afin d’éviter tout conflit avec un nom de propriété persistante. Pour éviter les chevauchements de noms de propriétés, vous pouvez ajouter un préfixe ou un suffixe à tous les noms de propriétés calculées. Cet article utilise le préfixe cp_ dans toutes les définitions de noms.

Important

La définition d’une propriété calculée à l’aide du même nom qu’une propriété persistante n’entraîne pas d’erreur, mais peut provoquer un comportement inattendu. Que la propriété calculée soit indexée ou non, les valeurs des propriétés persistantes qui partagent un nom avec une propriété calculée ne seront pas incluses dans l’index. Les requêtes utilisent toujours la propriété calculée au lieu de la propriété persistante, à l’exception de la propriété persistante retournée au lieu de la propriété calculée s’il existe une projection générique dans la clause SELECT. La projection de caractères génériques n’inclut pas automatiquement les propriétés calculées.

Les contraintes sur les noms de propriétés calculées sont les suivantes :

  • Toutes les propriétés calculées doivent avoir des noms uniques.
  • La valeur de la propriété name représente le nom de la propriété de niveau supérieur qui peut être utilisé pour référencer la propriété calculée.
  • Les noms de propriétés système réservées tels que id, _rid et _ts ne peuvent pas être utilisés comme noms de propriétés calculées.
  • Un nom de propriété calculé ne peut pas correspondre à un chemin de propriété déjà indexé. Cette contrainte s’applique à tous les chemins d’accès d’indexation spécifiés, notamment :
    • Chemins inclus
    • Chemins exclus
    • Index spatiaux
    • Index composites

Contraintes de requête

Les requêtes dans la définition de la propriété calculée doivent être valides d'un point de vue syntaxique et sémantique, sinon l'opération de création ou de mise à jour échoue. Les requêtes doivent être évaluées à une valeur déterministe pour tous les éléments d’un conteneur. Il est possible que des requêtes soient évaluées sur non définies ou nulles pour certains éléments et que propriétés calculées avec des valeurs non définies ou nulles se comportent comme des propriétés persistantes avec des valeurs non définies ou nulles lorsqu’elles sont utilisées dans des requêtes.

Les limitations concernant les définitions de requête de propriétés calculées sont les suivantes :

  • Les requêtes doivent spécifier une clause FROM représentant la référence d’élément racine. Des exemples de clauses FROM prises en charge sont : FROM c, FROM root c et FROM MyContainer c.
  • Les requêtes doivent utiliser une clause VALUE dans la projection.
  • Les requêtes ne peuvent pas inclure de clause JOIN.
  • Les requêtes ne peuvent pas utiliser d’expressions scalaires non déterministes. Exemples d’expressions scalaires non déterministes : GetCurrentDateTime, GetCurrentTimeStamp, GetCurrentTicks et RAND.
  • Les requêtes ne peuvent pas utiliser les clauses suivantes : WHERE, GROUP BY, ORDER BY, TOP, DISTINCT, OFFSET LIMIT, EXISTS, ALL et NONE.
  • Les requêtes ne peuvent pas inclure une sous-requête scalaire.
  • Les fonctions d’agrégation, les fonctions spatiales, les fonctions non déterministes et les fonctions définies par l’utilisateur (UDF) ne sont pas prises en charge.

Créer des propriétés calculées

Une fois les propriétés calculées créées, vous pouvez exécuter des requêtes qui les référencent à l’aide de n’importe quelle méthode, y compris tous les SDK et Azure Data Explorer dans le portail Azure.

Version prise en charge Notes
Kit de développement logiciel (SDK) .NET v3 >= 3.34.0-preview Les propriétés calculées sont actuellement disponibles uniquement dans les versions de package en préversion.
Kit SDK Java v4 >= 4.46.0 Les propriétés calculées sont actuellement en préversion.
Kit de développement logiciel (SDK) Python >= v4.5.2b5 Les propriétés calculées sont actuellement en préversion.

Créer des propriétés calculées à l’aide du kit de développement logiciel (SDK)

Vous pouvez créer un conteneur qui comprend des propriétés calculées définies ou ajouter des propriétés calculées à un conteneur existant.

Voici un exemple de création de propriétés calculées dans un nouveau conteneur :

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

Voici un exemple de mise à jour de propriétés calculées dans un conteneur existant :

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

Conseil

Chaque fois que vous mettez à jour des propriétés du conteneur, les anciennes valeurs sont remplacées. Si vous avez des propriétés calculées existantes et que vous souhaitez en ajouter de nouvelles, veillez à ajouter des propriétés calculées nouvelles et existantes à la collection.

Utiliser des propriétés calculées dans les requêtes

Les propriétés calculées peuvent être référencées dans les requêtes de la même manière que les propriétés persistantes. Les valeurs des propriétés calculées qui ne sont pas indexées sont évaluées pendant l’exécution à l’aide de la définition de propriété calculée. Si une propriété calculée est indexée, l’index est utilisé de la même manière que pour les propriétés persistantes, et la propriété calculée est évaluée en fonction des besoins. Nous vous recommandons d’ajouter des index à vos propriétés calculées pour optimiser les coûts et les performances.

Les exemples suivants utilisent le jeu de données de produits de démarrage rapide disponible dans Data Explorer dans le portail Azure. Pour commencer, sélectionnez Lancer le démarrage rapide, puis chargez le jeu de données dans un nouveau conteneur.

Capture d’écran qui montre comment commencer le démarrage rapide pour charger un exemple de jeu de données dans le portail Azure.

Voici un exemple d’élément :

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

Si les propriétés calculées doivent être projetées, elles doivent être référencées explicitement. Les projections de caractères génériques comme SELECT * renvoient toutes les propriétés persistantes, mais n’incluent pas les propriétés calculées.

Voici un exemple de définition de propriété calculée pour convertir la propriété name en minuscules :

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

Cette propriété peut ensuite être projetée dans une requête :

SELECT 
    c.cp_lowerName 
FROM 
    c

WHERE (clause)

Les propriétés calculées peuvent être référencées dans les prédicats de filtre comme toutes les propriétés persistantes. Nous vous recommandons d’ajouter tous les index uniques ou composites pertinents quand vous utilisez des propriétés calculées dans des filtres.

Voici un exemple de définition de propriété calculée pour calculer une remise de prix de 20 % :

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

Cette propriété pourrait ensuite être filtrée pour s’assurer que seuls les produits dont la remise serait inférieure à 50 $ sont retournés :

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

Clause GROUP BY

Comme pour les propriétés persistantes, les propriétés calculées peuvent être référencées dans la clause GROUP BY et utiliser l’index chaque fois que possible. Pour bénéficier de performances optimales, ajoutez tous les index uniques ou composites pertinents.

Voici un exemple de définition de propriété calculée qui recherche la catégorie principale pour chaque élément de la propriété categoryName :

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

Vous pouvez ensuite regrouper par cp_primaryCategory pour obtenir le nombre d’éléments dans chaque catégorie principale :

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

Conseil

Bien que vous puissiez également effectuer cette requête sans utiliser de propriétés calculées, l’utilisation des propriétés calculées simplifie considérablement l’écriture de la requête et permet d’augmenter les performances, car cp_primaryCategory peut être indexé. SUBSTRING() et INDEX_OF() nécessitent une analyse complète de tous les éléments du conteneur, mais si vous indexez la propriété calculée, la requête entière peut être traitée à partir de l’index à la place. La possibilité de traiter la requête à partir de l’index au lieu de s’appuyer sur une analyse complète augmente les performances et réduit les coûts d’unité de requête (RU).

Clause ORDER BY

À l’instar des propriétés persistantes, les propriétés calculées peuvent être référencées dans la clause ORDER BY et doivent être indexées pour que la requête réussisse. À l’aide de propriétés calculées, vous pouvez utiliser la clause ORDER BY sur le résultat de fonctions logiques ou système complexes, ce qui autorise de nombreux nouveaux scénarios de requête quand vous utilisez Azure Cosmos DB.

Voici un exemple de définition de propriété calculée qui obtient le mois hors de la valeur _ts :

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

Avant de pouvoir ORDER BY cp_monthUpdated, vous devez l’ajouter à votre stratégie d’indexation. Une fois votre stratégie d’indexation mise à jour, vous pouvez classer selon la propriété calculée.

SELECT
    *
FROM
    c
ORDER BY
    c.cp_monthUpdated

Indexer les propriétés calculées

Les propriétés calculées ne sont pas indexées par défaut et ne sont pas couvertes par des chemins génériques dans la stratégie d’indexation. Vous pouvez ajouter des index uniques ou composites sur des propriétés calculées dans la stratégie d’indexation comme vous le feriez pour ajouter des index sur les propriétés persistantes. Nous vous recommandons d'ajouter des index pertinents à toutes les propriétés calculées. Nous recommandons ces index car ils permettent d'augmenter les performances et de réduire les RU lorsqu'ils sont indexés. Lorsque les propriétés calculées sont indexées, les valeurs réelles sont évaluées pendant les opérations d’écriture d’élément pour générer et conserver les termes de l’index.

Voici quelques considérations à prendre en compte pour l’indexation des propriétés calculées :

  • Les propriétés calculées peuvent être spécifiées dans les chemins inclus, les chemins d’accès exclus et les chemins d’index composites.
  • Aucun index spatial ne peut être défini sur les propriétés calculées.
  • Les chemins d’accès génériques sous le chemin de propriété calculé fonctionnent comme ils le font pour les propriétés classiques.
  • Si vous supprimez une propriété calculée qui a été indexée, tous les index de cette propriété doivent également être supprimés.

Notes

Toutes les propriétés calculées sont définies au niveau supérieur de l’élément. Le chemin d’accès est toujours /<computed property name>.

Conseil

Chaque fois que vous mettez à jour des propriétés du conteneur, les anciennes valeurs sont remplacées. Si vous avez des propriétés calculées existantes et que vous souhaitez en ajouter de nouvelles, veillez à ajouter des propriétés calculées nouvelles et existantes à la collection.

Remarque

Lorsque la définition d’une propriété calculée indexée est modifiée, elle n’est pas réindexée automatiquement. Pour indexer la propriété calculée modifiée, vous devez d’abord supprimer la propriété calculée de l’index. Ensuite, une fois la réindexation terminée, ajoutez de nouveau la propriété calculée à la stratégie d’index.

Si vous souhaitez supprimer une propriété calculée, vous devez d’abord la supprimer de la stratégie d’index.

Ajouter un index unique pour les propriétés calculées

Pour ajouter un index unique pour une propriété calculée nommée cp_myComputedProperty :

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

Ajouter un index composite pour les propriétés calculées

Pour ajouter un index composite sur deux propriétés dans lesquelles, l'une est calculée comme cp_myComputedProperty, et l'autre persiste comme myPersistedProperty :

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

Comprendre la consommation d’unités de requête

L’ajout de propriétés calculées à un conteneur ne consomme aucune unité de requête. Les opérations en écriture sur des conteneurs dont les propriétés calculées sont définies peuvent présenter une légère augmentation des unités de requête. Si une propriété calculée est indexée, les unités de requête sur les opérations en écriture augmentent pour refléter les coûts d’indexation et d’évaluation de la propriété calculée.