Creating, Retrieving, Updating, and Deleting Entities

Data objects in Datastore are known as entities, each of which is categorized under a particular kind for the purpose of queries. For instance, if you are writing a human resources application you might represent each employee with an entity of kind Employee. Note that the entity data values are in the form of properties. For more information about entities, see the documentation on ancestor paths and transactions.

Creating entities and setting properties

You create an entity and set by calling the constructor method for its model class. See Creating and Using Entity Model Classes for information on creating an entity model class.

The following example shows how to invoke a model class constructor with keyword arguments:

sandy = Account(
    username='Sandy', userid=123, email='sandy@example.com')

This code creates an object in your program's main memory. However, note that the entity disappears when the process terminates, so you must also persist the entity to Datastore, by calling put(), as follows:

sandy_key = sandy.put()

Notice that this returns a key that you can use for retrieving the entity from Datastore later.

Set properties by using one of the following options:

  • Specify the entity's properties to the constructor with keyword arguments:
    sandy = Account(
        username='Sandy', userid=123, email='sandy@example.com')
  • Set properties manually after entity creation:
    sandy = Account()
    sandy.username = 'Sandy'
    sandy.userid = 123
    sandy.email = 'sandy@example.com'
  • Use the populate() convenience method to set several properties in one operation:
    sandy = Account()
    sandy.populate(
        username='Sandy',
        userid=123,
        email='sandy@gmail.com')

However you choose to set the entity's properties, the property types (in this case, StringProperty and IntegerProperty) enforce type checking.

For example:

bad = Account(
    username='Sandy', userid='not integer')  # raises an exception
...
sandy.username = 42  # raises an exception

Retrieving Entities from Keys

If you have an entity's key, you can retrieve the entity from Datastore:

sandy = sandy_key.get()

The Key methods kind() and id() recover the entity's kind and identifier from the key:

kind_string = sandy_key.kind()  # returns 'Account'
ident = sandy_key.id()  # returns '2'

You can also use an entity's key to obtain an encoded string suitable for embedding in a URL:

url_string = sandy_key.urlsafe()

This produces a result like agVoZWxsb3IPCxIHQWNjb3VudBiZiwIM which can later be used to reconstruct the key and retrieve the original entity:

sandy_key = ndb.Key(urlsafe=url_string)
sandy = sandy_key.get()

Notice that the URL-safe string looks cryptic, but it is not encrypted! It can easily be decoded to recover the original entity's kind and identifier:

key = Key(urlsafe=url_string)
kind_string = key.kind()
ident = key.id()

If you use such URL-safe keys, don't use sensitive data such as email addresses as entity identifiers. A possible solution would be to use a hash of the sensitive data as the identifier. This stops third parties, who can see the encrypted keys, from using them to harvest email addresses, though it doesn't stop them from independently generating their own hash of a known email address and using it to check whether that address is present in Datastore.

Updating entities

To update an existing entity, retrieve it from Datastore, modify its properties, and store it back again:

sandy = key.get()
sandy.email = 'sandy@example.co.uk'
sandy.put()

You can ignore the value returned by put() in this case, since an entity key doesn't change when you update it.

Deleting entities

When an entity is no longer needed, you can remove it from Datastore with the key's delete() method:

sandy.key.delete()

Note that this is an operation on the key, not on the entity itself. It always returns None.

Deleting entities in bulk

If you need to delete a large number of entities, we recommend using Dataflow to delete entities in bulk.

Using batch operations

You can process a collection of entities or keys in a single call rather than individually in separate calls, for example inside a loop. This results in a single remote procedure call (RPC) for the batch, rather than a separate RPC call for each entity.

The following code shows how you do this:

list_of_keys = ndb.put_multi(list_of_entities)
list_of_entities = ndb.get_multi(list_of_keys)
ndb.delete_multi(list_of_keys)

In the above code, you pass a list of key objects to ndb.get_multi to fetch multiple entities in a batch; ndb.get_multi returns a list of entity objects, with None values for keys that do not have a corresponding entity in Datastore. Getting the entities in this way results in fewer calls to Datastore for the entire batch. (The number of calls per batch depends on your batch size settings.)