Entités, propriétés et clés

Remarque : Les développeurs qui créent des applications sont vivement encouragés à utiliser la bibliothèque cliente NDB, qui présente plusieurs avantages supplémentaires par rapport à cette bibliothèque cliente, tels que la mise en cache automatique des entités via l'API Memcache. Si vous utilisez actuellement l'ancienne bibliothèque cliente DB, consultez le guide de migration de la bibliothèque cliente DB vers NDB.

Dans Cloud Datastore, les objets de données sont appelés entités. Une entité est associée à une ou plusieurs propriétés nommées, qui peuvent chacune avoir une ou plusieurs valeurs. Les entités du même genre ne doivent pas nécessairement avoir les mêmes propriétés. Par ailleurs, il n'est pas indispensable que toutes les valeurs d'une entité pour une propriété donnée correspondent au même type de données. Si nécessaire, une application peut définir et appliquer ces restrictions dans son propre modèle de données.

Cloud Datastore accepte divers types de données pour les valeurs de propriété, y compris les suivants :

  • Entiers
  • Nombres à virgule flottante
  • Chaînes
  • Dates
  • Données binaires

Pour obtenir la liste complète des types, consultez la section Propriétés et types de valeurs.

Chaque entité de Cloud Datastore possède une clé qui l'identifie de manière unique. La clé comprend les composants suivants :

  • L'espace de noms de l'entité, qui permet l'architecture mutualisée
  • Le genre de l'entité, qui la classe dans une catégorie pour les besoins des requêtes Cloud Datastore
  • Un identifiant pour chaque entité, qui peut être :
    • une chaîne de nom de clé ;
    • un ID numérique sous forme d'entier.
  • Un chemin d'ancêtre facultatif localisant l'entité dans la hiérarchie Cloud Datastore

Une application peut extraire une entité spécifique de Cloud Datastore à l'aide de la clé de l'entité, ou extraire une ou plusieurs entités en émettant une requête basée sur leurs clés ou leurs valeurs de propriétés.

Le SDK App Engine Python inclut une bibliothèque de modélisation de données permettant de représenter les entités Cloud Datastore sous la forme d'instances de classes Python, ainsi que de stocker et de récupérer ces instances dans Cloud Datastore.

Le service Cloud Datastore lui-même n'applique aucune restriction à la structure des entités pour déterminer, par exemple, si une propriété donnée a une valeur d'un type particulier. Cette tâche est du ressort de l'application et de la bibliothèque de modélisation de données.

Genres et identifiants

Chaque entité Cloud Datastore est d'un genre particulier, qui la classe dans une catégorie pour les besoins des requêtes. Par exemple, une application de ressources humaines peut représenter chaque employé d'une entreprise avec une entité du genre Employee. Dans l'API Datastore Python, le genre d'une entité est déterminé par la classe de son modèle, que vous définissez dans votre application en tant que sous-classe de la classe de la bibliothèque de modélisation de données db.Model. Le nom de la classe du modèle correspond au genre des entités qui appartiennent à cette dernière. Tous les noms de genre commençant par deux traits de soulignement (__) sont réservés et ne peuvent pas être utilisés.

L'exemple suivant permet de créer une entité du genre Employee, d'insérer ses valeurs de propriété et de l'enregistrer dans Datastore :

import datetime
from google.appengine.ext import db

class Employee(db.Model):
  first_name = db.StringProperty()
  last_name = db.StringProperty()
  hire_date = db.DateProperty()
  attended_hr_training = db.BooleanProperty()

employee = Employee(first_name='Antonio',
                    last_name='Salieri')

employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True

employee.put()

La classe Employee déclare quatre propriétés pour le modèle de données : first_name, last_name, hire_date et attended_hr_training. La super-classe Model garantit que les attributs des objets Employee sont conformes à ce modèle. Par exemple, toute tentative d'attribution d'une valeur de chaîne à l'attribut hire_date entraîne une erreur d'exécution, car le modèle de données correspondant à hire_date a été déclaré en tant que db.DateProperty.

En plus d'un genre, chaque entité possède un identifiant, qui lui est attribué au moment de sa création. Comme il fait partie de la clé de l'entité, l'identifiant est associé de manière permanente à celle-ci et ne peut pas être modifié. Il peut être attribué de deux manières :

  • L'application peut spécifier sa propre chaîne de nom de clé pour l'entité.
  • Vous pouvez demander à Cloud Datastore d'attribuer automatiquement à l'entité un ID numérique sous forme d'entier.

Pour attribuer un nom de clé à une entité, indiquez l'argument key_name nommé au constructeur de la classe de modèle lorsque vous créez l'entité.

# Create an entity with the key Employee:'asalieri'.
employee = Employee(key_name='asalieri')

Pour que Cloud Datastore attribue automatiquement un ID numérique, omettez l'argument key_name.

#NOTYPO
# Create an entity with a key such as Employee:8261.
employee = Employee()

Attribuer des identifiants

Cloud Datastore peut être configuré de façon à générer automatiquement des ID à l'aide de deux règles différentes :

  • La règle default génère une séquence aléatoire d'ID inutilisés qui sont répartis de manière à peu près uniforme. Chaque ID peut comporter jusqu'à 16 chiffres décimaux.
  • La règle legacy crée une séquence d'ID entiers plus petits non consécutifs.

Si vous souhaitez que les ID d'entité soient visibles par l'utilisateur et/ou si vous voulez les afficher dans l'ordre approprié, l'allocation manuelle est la meilleure solution.

Cloud Datastore génère une séquence aléatoire d'ID inutilisés qui sont répartis de manière à peu près uniforme. Chaque ID peut comporter jusqu'à 16 chiffres décimaux.

L'unicité des valeurs d'ID allouées par le système est garantie pour le groupe d'entités. Si vous copiez une entité d'un groupe d'entités ou d'un espace de noms dans un autre, et si vous souhaitez conserver la partie de la clé qui correspond à l'ID, veillez à d'abord allouer l'ID pour empêcher Cloud Datastore de le sélectionner en vue d'une attribution ultérieure.

Chemins d'ancêtre

Dans Cloud Datastore, les entités forment un espace structuré de manière hiérarchique, semblable à la structure de répertoires d'un système de fichiers. Lorsque vous créez une entité, vous pouvez éventuellement en désigner une autre comme son parent. La nouvelle entité est alors un enfant de l'entité parente. Sachez que contrairement à ce qui se produit dans un système de fichiers, l'entité parente n'a pas besoin d'exister réellement. Une entité sans parent est une entité racine. L'association entre une entité et son parent est permanente. Elle ne peut pas être modifiée une fois l'entité créée. Cloud Datastore n'attribue jamais le même ID numérique à deux entités ayant le même parent ou à deux entités racines (sans parent).

Les ancêtres d'une entité correspondent à son parent, au parent de son parent et ainsi de suite, de manière récursive. Ses descendants sont ses enfants, les enfants de ses enfants, etc. Une entité racine et tous ses descendants appartiennent au même groupe d'entités. La séquence d'entités commençant par une entité racine, puis allant du parent à l'enfant et menant à une entité donnée, constitue le chemin d'ancêtre de cette entité. La clé complète désignant l'entité se compose d'une séquence de paires genre/identifiant, qui spécifie son chemin d'ancêtre et se termine par les valeurs de l'entité elle-même :

[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]

Pour une entité racine, le chemin d'ancêtre est vide. La clé n'est constituée que du genre et de l'identifiant de l'entité.

[Person:GreatGrandpa]

Le schéma suivant illustre ce concept :

Groupe d'entités

Pour désigner le parent d'une entité, utilisez l'argument parent du constructeur de la classe de modèle lors de la création de l'entité enfant. La valeur de cet argument peut correspondre à l'entité parente elle-même ou à sa clé. Vous pouvez obtenir la clé en appelant la méthode key() de l'entité parente. L'exemple suivant permet de créer une entité du genre Address et montre deux manières de désigner une entité Employee comme son parent :

# Create Employee entity
employee = Employee()
employee.put()

# Set Employee as Address entity's parent directly...
address = Address(parent=employee)

# ...or using its key
e_key = employee.key()
address = Address(parent=e_key)

# Save Address entity to datastore
address.put()

Transactions et groupes d'entités

Toute tentative de création, de mise à jour ou de suppression d'une entité a lieu dans le cadre d'une transaction. Une même transaction peut inclure un nombre illimité d'opérations de ce type. Pour maintenir la cohérence des données, la transaction s'assure que toutes les opérations qu'elle contient sont appliquées à Cloud Datastore en tant qu'unité ou, en cas d'échec de l'une de ces opérations, qu'aucune d'entre elles n'est appliquée. En outre, toutes les lectures fortement cohérentes (requêtes ascendantes ou opérations "get") effectuées dans le cadre de la même transaction reposent sur un instantané cohérent des données.

Comme indiqué ci-dessus, un groupe d'entités est un ensemble d'entités connectées par le biais d'un ancêtre à un élément racine commun. L'organisation des données sous forme de groupes d'entités peut limiter les transactions susceptibles d'être effectuées :

  • Toutes les données auxquelles accède une transaction doivent être contenues dans 25 groupes d'entités au maximum.
  • Si vous souhaitez employer des requêtes dans une transaction, les données doivent être organisées sous forme de groupes d'entités de sorte que vous puissiez spécifier des filtres d'ancêtres qui correspondent aux données appropriées.
  • Le débit en écriture est limité à environ une transaction par seconde pour un même groupe d'entités. Cette limite a été définie, car Cloud Datastore effectue une réplication synchrone sans maître de chaque groupe d'entités sur une vaste zone géographique afin de garantir un haut niveau de fiabilité et de tolérance aux pannes.

Dans de nombreuses applications, vous pouvez faire appel à la cohérence à terme (c'est-à-dire à une requête non ascendante couvrant plusieurs groupes d'entités et renvoyant parfois des données légèrement obsolètes) lorsque vous obtenez une vue d'ensemble de données non liées, puis utiliser la cohérence forte (requête ascendante ou opération get sur une seule entité) lorsque vous visualisez ou modifiez un seul ensemble de données étroitement liées. Dans ces applications, il est généralement recommandé d'utiliser un groupe d'entités distinct pour chaque ensemble de données étroitement liées. Pour en savoir plus, consultez la page Structurer les données pour la cohérence forte.

Propriétés et types de valeurs

Les valeurs de données associées à une entité se composent d'une ou de plusieurs propriétés. Chaque propriété a un nom, de même qu'une ou plusieurs valeurs. Une propriété peut avoir des valeurs de divers types. Par ailleurs, deux entités peuvent avoir des valeurs de types différents pour la même propriété. Une propriété peut être indexée ou non indexée. Les requêtes qui trient ou filtrent en fonction d'une propriété P ignorent les entités pour lesquelles cette propriété P n'est pas indexée. Une entité peut avoir 20 000 propriétés indexées au maximum.

Les types de valeurs ci-dessous sont acceptés.

Type de valeur Type(s) Python Ordre de tri Notes
Entier int
long
Numérique Entier de 64 bits signé
Nombre à virgule flottante float Numérique Double précision 64 bits,
IEEE 754
Booléen bool False < True
Chaîne de texte (courte) str
unicode
Unicode
(données str traitées comme des caractères ASCII)
Jusqu'à 1 500 octets
Chaîne de texte (longue) db.Text Aucun Jusqu'à 1 mégaoctet

Pas indexé
Chaîne d'octets (courte) db.ByteString Ordre des octets Jusqu'à 1 500 octets
Chaîne d'octets (longue) db.Blob Aucun Jusqu'à 1 mégaoctet

Pas indexé
Date et heure datetime.date
datetime.time
datetime.datetime
Chronologique
Point géographique db.GeoPt Par latitude,
puis par longitude
Adresse postale db.PostalAddress Unicode
Numéro de téléphone db.PhoneNumber Unicode
Adresse e-mail db.Email Unicode
Utilisateur disposant d'un compte Google users.User Adresse e-mail
dans l'ordre Unicode
Descripteur de messagerie instantanée db.IM Unicode
Lien db.Link Unicode
Catégorie db.Category Unicode
Note db.Rating Numérique
Clé Cloud Datastore db.Key Par éléments de chemin
(genre, identifiant,
genre, identifiant…)
Clé Blobstore blobstore.BlobKey Ordre des octets
Vide NoneType Aucun

Important : Nous vous recommandons vivement de ne pas stocker de propriété UserProperty, car elle contient l'adresse e-mail et l'ID unique de l'utilisateur. Imaginez qu'un utilisateur modifie son adresse e-mail. Si vous comparez l'ancienne valeur User stockée à la nouvelle valeur User, elles ne correspondent pas.

Pour les chaînes de texte et les données binaires non codées (chaînes d'octets), Cloud Datastore accepte deux types de valeurs :

  • Les chaînes courtes (jusqu'à 1 500 octets) sont indexées, et peuvent être utilisées dans les conditions de filtres de requêtes et les ordres de tri.
  • Les chaînes longues (jusqu'à 1 Mo) ne sont pas indexées, et ne peuvent pas être utilisées dans les filtres de requêtes et les ordres de tri.
Remarque : Le type d'une chaîne d'octets longue est appelé Blob dans l'API Cloud Datastore. Il n'a pas de rapport avec les blobs utilisés dans l'API Blobstore.

Lorsqu'une requête implique une propriété avec des valeurs de types différents, Cloud Datastore utilise un ordre déterministe basé sur les représentations internes.

  1. Valeurs Null
  2. Nombres à virgule fixe
    • Entiers
    • Dates et heures
    • Notes
  3. Valeurs booléennes
  4. Séquences d'octets
    • Chaîne d'octets
    • Chaîne Unicode
    • Clés Blobstore
  5. Nombres à virgule flottante
  6. Points géographiques
  7. Utilisateurs disposant d'un compte Google
  8. Clés Cloud Datastore

Aucun ordre n'est défini pour les chaînes de texte longues et les chaînes d'octets longues, car elles ne sont pas indexées.

Utiliser des entités

Les applications peuvent faire appel à l'API Cloud Datastore pour créer, récupérer, mettre à jour et supprimer des entités. Si l'application connaît la clé complète d'une entité (ou si elle a la possibilité de la déduire de la clé parente, du genre et de l'identifiant), elle peut s'en servir pour effectuer des opérations directement sur l'entité. Une application peut également obtenir la clé d'une entité à la suite d'une requête Cloud Datastore. Pour en savoir plus, consultez la page Requêtes Datastore.

Créer une entité

En Python, vous pouvez créer une entité en générant une instance d'une classe de modèle, en indiquant si nécessaire ses propriétés et en appelant sa méthode put() pour l'enregistrer dans Datastore. Vous avez la possibilité de spécifier le nom de la clé de l'entité en transmettant un argument key_name au constructeur.

employee = Employee(key_name='asalieri',
                    first_name='Antonio',
                    last_name='Salieri')

employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True

employee.put()

Si vous n'indiquez pas de nom de clé, Cloud Datastore génère automatiquement un ID numérique pour la clé de l'entité.

employee = Employee(first_name='Antonio',
                    last_name='Salieri')

employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True

employee.put()

Récupérer une entité

Pour récupérer une entité identifiée par une clé donnée, transmettez l'objet Key en tant qu'argument à la fonction db.get(). Vous pouvez générer l'objet Key à l'aide de la méthode de classe Key.from_path(). Le chemin complet correspond à une séquence d'entités du chemin d'ancêtre. Chaque entité est représentée par son genre (chaîne), suivi de son identifiant (nom de clé ou ID numérique) :

address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
address = db.get(address_k)

db.get() renvoie une instance de la classe de modèle appropriée. Assurez-vous que vous avez importé la classe de modèle pour l'entité en cours de récupération.

Mettre à jour une entité

Pour mettre à jour une entité existante, modifiez les attributs de l'objet, puis appelez sa méthode put(). Les données de l'objet écrasent l'entité existante. L'objet entier est envoyé à Cloud Datastore à chaque appel de put()

Pour supprimer une propriété, supprimez l'attribut de l'objet Python :

del address.postal_code

Ensuite, enregistrez l'objet.

Supprimer une entité

La fonction db.delete() permet de supprimer une entité en fonction de sa clé.

address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
db.delete(address_k)

Vous pouvez également supprimer une entité en appelant sa méthode delete() :

employee_k = db.Key.from_path('Employee', 'asalieri')
employee = db.get(employee_k)

# ...

employee.delete()

Opérations par lot

Les fonctions db.put(), db.get() et db.delete() (et leurs équivalents asynchrones db.put_async(), db.get_async() et db.delete_async()) peuvent accepter qu'un argument de liste s'applique à plusieurs entités d'un même appel Cloud Datastore :

# A batch put.
db.put([e1, e2, e3])

# A batch get.
entities = db.get([k1, k2, k3])

# A batch delete.
db.delete([k1, k2, k3])

Les opérations par lots n'entraînent pas de modification des coûts. Chaque clé employée dans ces opérations vous est facturée, qu'elle existe ou non. La taille des entités impliquées dans une opération n'a pas d'incidence sur les coûts.

Suppression groupée d'entités

Si vous devez supprimer un grand nombre d'entités, nous vous recommandons d'utiliser Cloud Dataflow pour effectuer des opérations de suppression groupées.

Utiliser une liste vide

Pour l'interface NDB, Cloud Datastore spécifiait jusqu'à présent une liste vide en tant que propriété omise pour les propriétés statiques et dynamiques. Pour assurer la rétrocompatibilité, ce comportement s'applique toujours par défaut. Pour ignorer ce comportement globalement ou en fonction de la propriété ListProperty, définissez l'argument write_empty_list sur true dans la classe Property. La liste vide est alors écrite dans Cloud Datastore. Elle peut être lue en tant que liste vide.

Pour l'interface DB, il était jusque-là totalement interdit de créer des listes vides si la propriété était dynamique. Si vous tentiez d'effectuer cette opération, vous receviez un message d'erreur. Par conséquent, aucun comportement par défaut ne doit être conservé à des fins de rétrocompatibilité pour les propriétés dynamiques DB. Il vous suffit donc d'écrire et de lire la liste vide dans le modèle dynamique sans apporter de modification.

Toutefois, pour les propriétés statiques DB, la liste vide était spécifiée en tant que propriété omise. Ce comportement s'applique toujours par défaut pour assurer la rétrocompatibilité. Si vous souhaitez activer les listes vides pour les propriétés statiques DB, définissez l'argument write_empty_list sur true dans la classe Property. La liste vide est alors écrite dans Cloud Datastore.

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Environnement standard App Engine pour Python