Créer et utiliser des clés d'entité

Chaque entité est identifiée par une clé qui est unique dans l'instance Datastore de l'application et comprend les éléments suivants :

  • Genre – Il s'agit généralement du nom de la classe de modèle à laquelle appartient l'entité, mais vous pouvez le remplacer par une autre chaîne en ignorant la méthode de classe _get_kind().
  • Identifiant – Spécifiez votre propre nom de clé comme identifiant ou laissez Datastore générer automatiquement un ID numérique sous forme d'entier.

Spécifier votre propre nom de clé

L'exemple suivant permet de créer implicitement une clé avec un identifiant de chaîne à l'aide du paramètre nommé id :

account = Account(
    username='Sandy', userid=1234, email='sandy@example.com',
    id='sandy@example.com')

return account.key.id()  # returns 'sandy@example.com'

Vous pouvez également définir le nom de clé directement :

account.key = ndb.Key('Account', 'sandy@example.com')

# You can also use the model class object itself, rather than its name,
# to specify the entity's kind:
account.key = ndb.Key(Account, 'sandy@example.com')

Laisser Datastore générer un ID qui servira de clé

Ce code montre comment utiliser un ID généré automatiquement comme clé :

# note: no id kwarg
account = Account(username='Sandy', userid=1234, email='sandy@example.com')
account.put()
# account.key will now have a key of the form: ndb.Key(Account, 71321839)
# where the value 71321839 was generated by Datastore for us.

Utiliser le chemin d'ancêtre dans la clé

La séquence d'entités commençant par une entité racine, puis allant du parent à l'enfant pour arriver à une entité donnée, constitue le chemin d'ancêtre de cette entité. Le parent, le parent du parent et ainsi de suite, sont les ancêtres d'une entité. Les entités du datastore forment donc un espace de clés structuré de manière hiérarchique, semblable à la structure de répertoires d'un système de fichiers.

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. La méthode constructeur de la classe Key accepte ce type de séquence de genres et d'identifiants, et renvoie un objet représentant la clé de l'entité correspondante.

L'exemple suivant montre un service de création de blogs qui stocke des messages par révision. Les messages sont regroupés par compte, et les révisions par message.

class Revision(ndb.Model):
    message_text = ndb.StringProperty()
...
ndb.Key('Account', 'sandy@example.com', 'Message', 123, 'Revision', '1')
ndb.Key('Account', 'sandy@example.com', 'Message', 123, 'Revision', '2')
ndb.Key('Account', 'larry@example.com', 'Message', 456, 'Revision', '1')
ndb.Key('Account', 'larry@example.com', 'Message', 789, 'Revision', '2')

Dans l'exemple de code ci-dessus, ('Account', 'sandy@example.com'), ('Message', 123) et ('Revision', '1') sont tous des exemples de paires genre/identifiant.

Notez que Message n'est pas une classe de modèle. Il ne sert qu'à regrouper les révisions et non à stocker des données.

Comme indiqué dans l'exemple de code, le genre de l'entité est désigné par la dernière paire genre/nom de la liste : ndb.Key('Revision', '1').

Utiliser des paramètres nommés

Vous pouvez désigner directement une entité dans le chemin d'ancêtre au moyen du paramètre nommé parent. Les notations suivantes représentent toutes la même clé :

ndb.Key('Account', 'sandy@example.com', 'Message', 123, 'Revision', '1')

ndb.Key('Revision', '1', parent=ndb.Key(
    'Account', 'sandy@example.com', 'Message', 123))

ndb.Key('Revision', '1', parent=ndb.Key(
    'Message', 123, parent=ndb.Key('Account', 'sandy@example.com')))

Spécifier une entité racine

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

sandy_key = ndb.Key(Account, 'sandy@example.com')

Spécifier une entité avec des ancêtres

Pour insérer un nouveau message avec des clés parentes :

account_key = ndb.Key(Account, 'sandy@example.com')

# Ask Datastore to allocate an ID.
new_id = ndb.Model.allocate_ids(size=1, parent=account_key)[0]

# Datastore returns us an integer ID that we can use to create the message
# key
message_key = ndb.Key('Message', new_id, parent=account_key)

# Now we can put the message into Datastore
initial_revision = Revision(
    message_text='Hello', id='1', parent=message_key)
initial_revision.put()

Pour les clés créées avec un parent, la méthode parent() renvoie une clé représentant l'entité parente :

message_key = initial_revision.key.parent()

Utiliser des ID de clé numériques

Vous pouvez créer une entité sans spécifier d'ID, auquel cas le datastore génère automatiquement un ID numérique. Si vous choisissez de spécifier certains ID, puis que vous laissez Datastore en générer automatiquement d'autres, l'exigence d'unicité des clés risque de ne pas être respectée. Pour éviter que cela ne se produise, réservez une plage de nombres à utiliser comme ID. Sinon, l'emploi d'ID de chaîne permet de remédier complètement à ce problème.

Pour réserver une plage d'ID, utilisez la méthode de classe allocate_ids() de la classe de modèle :

  • pour allouer un nombre déterminé d'ID ;
  • pour allouer tous les ID jusqu'à une valeur maximale donnée.

Allouer des ID

Pour allouer 100 ID pour une classe de modèle donnée (MyModel) :

first, last = MyModel.allocate_ids(100)

Pour allouer 100 ID pour les entités ayant la clé parente p :

first, last = MyModel.allocate_ids(100, parent=p)

Les valeurs renvoyées, first et last, sont les premier et dernier ID (inclus) alloués. Vous pouvez vous en servir pour construire des clés comme suit :

keys = [ndb.Key(MyModel, id) for id in range(first, last+1)]

Vous avez la garantie que ces clés n'ont pas déjà été renvoyées par le générateur d'ID internes du datastore et qu'elles ne seront pas renvoyées par des appels ultérieurs au générateur d'ID internes. Cependant, la méthode allocate_ids() ne vérifie pas si les ID renvoyés sont présents dans le datastore. Elle n'interagit qu'avec le générateur d'ID.

Pour allouer tous les ID jusqu'à une valeur maximale donnée :

first, last = MyModel.allocate_ids(max=N)

Ce formulaire garantit que tous les ID inférieurs ou égaux à N sont considérés comme alloués. Les valeurs renvoyées, first et last, indiquent la plage d'ID réservée par cette opération. La tentative de réservation d'ID déjà alloués n'entraîne pas une erreur. Si cela se produit, first indique le premier ID non encore alloué, et last est le dernier ID alloué.