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 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é a une ou plusieurs propriétés nommées, chacune pouvant avoir une ou plusieurs valeurs. Les entités du même genre n'ont pas besoin d'avoir les mêmes propriétés, et il n'est pas nécessaire que les valeurs d'une entité pour une propriété donnée soient toutes du même type de données. (Si nécessaire, une application peut établir et appliquer de telles restrictions dans son propre modèle de données.)

Cloud Datastore est compatible avec divers types de données pour les valeurs de propriété, parmi lesquels :

  • 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é dans Cloud Datastore possède une clé qui l'identifie de manière unique. Cette dernière comprend les composants suivants :

  • L'espace de noms de l'entité, qui permet de définir l'architecture mutualisée.
  • Le genre de l'entité, qui permet de classer celle-ci pour les besoins des requêtes Cloud Datastore.
  • Un identifiant associé à l'entité de manière individuelle, qui peut être :
    • une chaîne de nom de clé ;
    • un ID numérique sous forme d'entier.
  • Un chemin d'ancêtre facultatif qui situe l'entité dans la hiérarchie Cloud Datastore

Une application peut extraire une entité individuelle 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.

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

Attribuer des identifiants

Cloud Datastore peut être configuré de sorte à générer des identifiants automatiques à l'aide de deux règles d'ID automatique différentes :

  • La règle default génère une séquence aléatoire d'ID inutilisés distribués d'une manière approximativement 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 souhaitez les afficher en fonction de leur ordre, 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.

Les valeurs d'ID allouées par le système sont garanties uniques au groupe d'entités. Si vous copiez une entité d'un groupe d'entités ou d'un espace de nommage dans un autre, et que vous souhaitez conserver la partie ID de la clé, 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êtres

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. 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, et elle ne peut plus ê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 (celles 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 identifiant l'entité consiste en 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, et la clé est constituée uniquement du genre et de l'identifiant de l'entité :

[Person:GreatGrandpa]

Le schéma suivant illustre ce concept :

Affiche la relation entre l'entité racine et les entités enfants dans le 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 seule transaction peut inclure n'importe quel nombre 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 d'une même transaction reposent sur un instantané cohérent des données.

Comme mentionné 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 en groupes d'entités peut limiter le nombre de transactions pouvant ê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 en 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 seul groupe d'entités. Cette limite existe parce que Cloud Datastore effectue une réplication synchrone sans maître de chaque groupe d'entités sur une vaste zone géographique afin de fournir une fiabilité et une tolérance aux pannes élevées.

Dans de nombreuses applications, il est acceptable de recourir à la cohérence à terme (à savoir à une requête non ascendante couvrant plusieurs groupes d'entités et pouvant parfois renvoyer des données légèrement obsolètes) lors de l'obtention d'une vue d'ensemble de données non liées, puis de passer à la cohérence forte (requête ascendante ou opération get d'une seule entité) lors de la visualisation ou de la modification d'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 des données pour renforcer la cohérence.

Propriétés et types de valeurs

Les valeurs de données associées à une entité consistent en une ou plusieurs propriétés. Chaque propriété a un nom, et une ou plusieurs valeurs. Une propriété peut avoir des valeurs de plus d'un type, et 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 ignoreront les entités où cette propriété P est non indexée). Une entité peut avoir 20 000 propriétés indexées au maximum.

Les types de valeurs suivants 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înes d'octets (courtes) 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 de Google Accounts 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 filtre 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ête 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 différents types, Cloud Datastore emploie 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

Étant donné que les chaînes de texte et d'octets longues ne sont pas indexées, aucun tri n'est défini pour celles-ci.

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 peut la déduire de sa clé parente, de son genre et de son 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 plus d'informations, 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 lot n'entraînent pas de modification des coûts. Vous serez facturé pour chaque clé employée dans ces opérations, que cette clé 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, et elle peut être lue en tant que telle.

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 2