Python 2.7 has reached end of supportand will bedeprecatedon January 31, 2026. After deprecation, you won't be able to deploy Python 2.7applications, even if your organization previously used an organization policy tore-enable deployments of legacy runtimes. Your existing Python2.7 applications will continue to run and receive traffic after theirdeprecation date. We recommend thatyoumigrate to the latest supported version of Python.

Entities, Properties, and Keys

Note:Developers building new applications arestrongly encouraged to use theNDB Client Library, which has several benefitscompared to this client library, such as automatic entity caching via the MemcacheAPI. If you are currently using the older DB Client Library, read theDB to NDB Migration Guide

Data objects in Datastore are known asentities. An entityhas one or more namedproperties, each of which can have one or more values.Entities of the same kind do not need to have the same properties, and anentity's values for a given property do not all need to be of the same datatype. (If necessary, an application can establish and enforce such restrictionsin its own data model.)

Datastore supports a variety ofdata types for property values.These include, among others:

  • Integers
  • Floating-point numbers
  • Strings
  • Dates
  • Binary data

For a full list of types, seeProperties and value types.

Each entity in Datastore has akey that uniquely identifies it. The key consists of the following components:

  • Thenamespace of the entity, which allows formultitenancy
  • Thekind of the entity, which categorizes it for the purpose of Datastore queries
  • Anidentifier for the individual entity, which can be either
    • akey name string
    • an integernumeric ID
  • An optionalancestor path locating the entity within the Datastore hierarchy
Don't name a property "key." This name is reservedfor a special property used to store the Model key. Though it may worklocally, a property named "key" will prevent deployment to App Engine.

An application can fetch an individual entityfrom Datastore using the entity's key, or it can retrieve one or more entitiesby issuing aquery based on the entities' keys or property values.

The Python App Engine SDK includes adata modeling library for representing Datastore entities as instances of Python classes, and for storing and retrieving those instances in Datastore.

Datastore itself does not enforce any restrictions on the structure of entities, such as whether a given property has a value of a particular type; this task is left to the application and the data modeling library.

Kinds and identifiers

Each Datastore entity is of a particularkind, which categorizes the entity for the purpose of queries: for instance, a human resources application might represent each employee at a company with an entity of kindEmployee. In the Python Datastore API, an entity's kind is determined by itsmodel class, which you define in your application as a subclass of the data modeling library classdb.Model. The name of the model class becomes the kind of the entities belonging to it. All kind names that begin with two underscores (__) are reserved and may not be used.

The following example creates an entity of kindEmployee, populates its property values, and saves it to Datastore:

importdatetimefromgoogle.appengine.extimportdbclassEmployee(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=Trueemployee.put()

TheEmployee class declares four properties for the data model:first_name,last_name,hire_date, andattended_hr_training. TheModel superclass ensures that the attributes ofEmployee objects conform to this model: for example, an attempt to assign a string value to thehire_date attribute would result in a runtime error, since the data model forhire_date was declared asdb.DateProperty.

In addition to a kind, each entity has anidentifier, assigned when the entity is created. Because it is part of the entity's key, the identifier is associated permanently with the entity and cannot be changed. It can be assigned in either of two ways:

  • Your application can specify its ownkey name string for the entity.
  • You can have Datastore automatically assign the entity an integernumeric ID.

To assign an entity a key name, provide the named argumentkey_name to the model class constructor when you create the entity:

# Create an entity with the key Employee:'asalieri'.employee=Employee(key_name='asalieri')
Note:
  • Key names cannot begin and end with two underscores(__*__)
  • In addition to arguments such askey_name, theModel constructor accepts initial values for properties as keyword arguments. This makes it inconvenient to have a property namedkey_name.
For more information, see
Disallowed Property Names.

To have Datastore assign a numeric ID automatically, omit thekey_name argument:

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

Assigning identifiers

Datastore can be configured to generate auto IDs usingtwo different auto id policies:

  • Thedefault policy generates a random sequence of unused IDs that are approximately uniformly distributed. Each ID can be up to 16 decimal digits long.
  • Thelegacy policy creates a sequence of non-consecutive smaller integer IDs.

If you want to display the entity IDs to the user, and/or depend upon their order, the best thing to do is use manual allocation.

Note: Instead of using key name strings or generating numeric IDs automatically, advanced applications may sometimes wish to assign their own numeric IDs manually to the entities they create. Be aware, however, that there is nothing to prevent Datastore from assigning one of your manual numeric IDs to another entity. The only way to avoid such conflicts is to have your application obtain a block of IDs with the methodsallocate_ids() orallocate_ids_async(). Datastore's automatic ID generator will keep track of IDs that have been allocated with these methods and will avoid reusing them for another entity, so you can safely use such IDs without conflict.

Datastore generates a random sequence of unused IDs that are approximately uniformly distributed. Each ID can be up to 16 decimal digits long.

Ancestor paths

Entities in Cloud Datastore form a hierarchically structured space similar tothe directory structure of a file system. When you create an entity, you canoptionally designate another entity as itsparent; the new entity is achild of the parent entity (note that unlike in a file system, the parententity need not actually exist). An entity without a parent is arootentity. The association between an entity and its parent is permanent, andcannot be changed once the entity is created. Cloud Datastore will never assignthe same numeric ID to two entities with the same parent, or to two rootentities (those without a parent).

An entity's parent, parent's parent, and so on recursively, are itsancestors; its children, children's children, and so on, are itsdescendants. A root entity and all of its descendants belong tothe sameentity group. The sequence of entities beginning with a rootentity and proceeding from parent to child, leading to a given entity,constitute that entity'sancestor path. The complete key identifyingthe entity consists of a sequence of kind-identifier pairs specifying itsancestor path and terminating with those of the entity itself:

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

For a root entity, the ancestor path is empty and the key consists solely ofthe entity's own kind and identifier:

[Person:GreatGrandpa]

This concept is illustrated by the following diagram:

Shows relationship of root entity to child  entities in entity group

To designate an entity's parent, use theparent argument to the model class constructor when creating the child entity. The value of this argument can be the parent entity itself or its key; you can get the key by calling the parent entity'skey() method. The following example creates an entity of kindAddress and shows two ways of designating anEmployee entity as its parent:

# Create Employee entityemployee=Employee()employee.put()# Set Employee as Address entity's parent directly...address=Address(parent=employee)# ...or using its keye_key=employee.key()address=Address(parent=e_key)# Save Address entity to datastoreaddress.put()

Transactions and entity groups

Every attempt to create, update, or delete an entity takes place in the contextof atransaction.A single transaction can include any number of such operations. To maintain theconsistency of the data, the transaction ensures that all of the operations itcontains are applied to Datastore as a unit or, if any of theoperations fails, that none of them are applied. Furthermore, all strongly-consistent reads (ancestor queries or gets) performed within the sametransaction observe a consistent snapshot of the data.

Note: If your application receives an exception when attempting to commit a transaction, it does not necessarily mean that the transaction has failed. It is possible to receive aTimeout,TransactionFailedError, orInternalError exception even when a transaction has been committed and will eventually be applied successfully. Whenever possible, structure your Datastore transactions so that the end result will be unaffected if the same transaction is applied more than once.

As mentioned above, an entity group is a set of entities connected through ancestry to a common root element. The organization of data into entity groups can limit what transactions can be performed:

  • All the data accessed by a transaction must be contained in at most 25 entity groups.
  • If you want to use queries within a transaction, your data must be organized into entity groups in such a way that you can specify ancestor filters that will match the right data.
  • There is a write throughput limit of about one transaction per second within a single entity group. This limitation exists because Datastore performs masterless, synchronous replication of each entity group over a wide geographic area to provide high reliability and fault tolerance.

In many applications, it is acceptable to use eventual consistency (i.e. a non-ancestor query spanning multiple entity groups, which may at times return slightly stale data) when obtaining a broad view of unrelated data, and then to use strong consistency (an ancestor query, or aget of a single entity) when viewing or editing a single set of highly related data. In such applications, it is usually a good approach to use a separate entity group for each set of highly related data.For more information, seeStructuring for Strong Consistency.

Note: Avoid storing sensitive information in the entity group key. Entity group keys may be retained after the entity group is deleted in order to provide fast and reliable service across Datastore.

Properties and value types

The data values associated with an entity consist of one or moreproperties. Each property has a name and one or more values. A property can have values of more than one type, and two entities can have values of different types for the same property. Properties can be indexed or unindexed (queries that order or filter on a propertyP will ignore entities whereP is unindexed). An entity can have at most 20,000 indexed properties.

Note: Properties with multiple values can be useful, for instance, when performing queries with equality filters: an entity satisfies the query if any of its values for a property matches the value specified in the filter. For more details on multiple-valued properties, including issues you should be aware of, see theDatastore Queries page.

The following value types are supported:

Value typePython type(s)Sort orderNotes
Integerint
long
Numeric64-bit integer, signed
Floating-point numberfloatNumeric64-bit double precision,
IEEE 754
BooleanboolFalse<True
Text string (short)str
unicode
Unicode
(str treated as ASCII)
Up to 1500 bytes
Text string (long)db.TextNoneUp to 1 megabyte

Not indexed
Byte string (short)db.ByteStringByte orderUp to 1500 bytes
Byte string (long)db.BlobNoneUp to 1 megabyte

Not indexed
Date and timedatetime.date
datetime.time
datetime.datetime
Chronological
Geographical pointdb.GeoPtBy latitude,
then longitude
Postal addressdb.PostalAddressUnicode
Telephone numberdb.PhoneNumberUnicode
Email addressdb.EmailUnicode
Google Accounts userusers.UserEmail address
in Unicode order
Instant messaging handledb.IMUnicode
Linkdb.LinkUnicode
Categorydb.CategoryUnicode
Ratingdb.RatingNumeric
Datastore keydb.KeyBy path elements
(kind, identifier,
kind, identifier...)
Blobstore keyblobstore.BlobKeyByte order
NullNoneTypeNone

Important: We strongly recommend that you do notstore aUserProperty, since it includes the email addressand the user's unique ID. If a user changes their email address and you compare their old, storedUser to the newUser value, they won't match.

For text strings and unencoded binary data (byte strings), Datastore supports two value types:

  • Short strings (up to 1500 bytes) are indexed and can be used in query filter conditions and sort orders.
  • Long strings (up to 1 megabyte) are not indexed and cannot be used in query filters and sort orders.
Note: The long byte string type is namedBlob in the Datastore API. This type is unrelated to blobs as used in theBlobstore API.

When a query involves a property with values of mixed types, Datastore uses a deterministic ordering based on the internal representations:

  1. Null values
  2. Fixed-point numbers
    • Integers
    • Dates and times
    • Ratings
  3. Boolean values
  4. Byte sequences
    • Byte string
    • Unicode string
    • Blobstore keys
  5. Floating-point numbers
  6. Geographical points
  7. Google Accounts users
  8. Datastore keys

Because long text strings and long byte strings are not indexed, they have no ordering defined.

Note: Integers and floating-point numbers are considered separate types in Datastore. If an entity uses a mix of integers and floats for the same property, all integers will be sorted before all floats: for example,

7 <3.2

Working with entities

Applications can use the Datastore API to create, retrieve, update, and delete entities. If the application knows the complete key for an entity (or can derive it from its parent key, kind, and identifier), it can use the key to operate directly on the entity. An application can also obtain an entity's key as a result of a Datastore query; see theDatastore Queries page for more information.

Creating an entity

In Python, you create a new entity by constructing an instance of a model class, populating its properties if necessary, and calling itsput() method to save it to Datastore. You can specify the entity's key name by passing a key_name argument to the constructor:

employee=Employee(key_name='asalieri',first_name='Antonio',last_name='Salieri')employee.hire_date=datetime.datetime.now().date()employee.attended_hr_training=Trueemployee.put()

If you don't provide a key name, Datastore will automatically generate a numeric ID for the entity's key:

employee=Employee(first_name='Antonio',last_name='Salieri')employee.hire_date=datetime.datetime.now().date()employee.attended_hr_training=Trueemployee.put()

Retrieving an entity

To retrieve an entity identified by a given key, pass theKey object as an argument to thedb.get() function. You can generate theKey object using the class methodKey.from_path().The complete path is a sequence of entities in the ancestor path, with each entity represented by its kind (a string) followed by its identifier (key name or numeric ID):

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

db.get() returns an instance of the appropriate model class. Be sure that you have imported the model class for the entity being retrieved.

Updating an entity

To update an existing entity, modify the attributes of the object, then call itsput() method. The object data overwrites the existing entity. The entire object is sent to Datastore with every call toput().

Note: The Datastore API does not distinguish between creating a new entity and updating an existing one. If the object's key represents an entity that already exists, theput() method overwrites the existing entity. You can use a transaction to test whether an entity with a given key exists before creating one. See also theModel.get_or_insert() method.

To delete a property, delete the attribute from the Python object:

deladdress.postal_code

then save the object.

Deleting an entity

Given an entity's key, you can delete the entity with thedb.delete() function

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

or by calling the entity's owndelete() method:

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

Batch operations

Thedb.put(),db.get(), anddb.delete() functions (and their asynchronous counterpartsdb.put_async(),db.get_async(), anddb.delete_async()) can accept a list argument to act on multiple entities in a single Datastore call:

# 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])

Batch operations do not change your costs. You will be charged forevery key in a batched operation, whether or not each key exists.The size of the entities involved in an operation does not affect the cost.

Note: A batch call todb.put() ordb.delete() may succeed for some entities but not others. If it is important that the call succeed completely or fail completely, you must use a transaction, and all affected entities must be in the same entity group.

Deleting entities in bulk

If you need to delete a large number of entities, we recommendusingDataflow to delete entities in bulk.

Using an empty list

For the NDB interface, Datastore historically wrote an empty list as an omittedproperty for both static and dynamic properties. To maintain backwardcompatibility, this behavior continues to be the default. To override this eitherglobally or on a per ListProperty basis, set thewrite_empty_listargument totrue in your Property class; the empty list is then written toDatastore and can be read as an empty list.

For the DB interface, empty list writes were historically not allowed at allif the property was dynamic: if you attempted this yougot an error. This means that there is no default behavior needing to bepreserved for backwards compatibility for DB dynamic properties, and so you cansimply write and read the empty list in the dynamic model without any changes.

However, for DB static properties, the empty list was written as an omittedproperty, and this behavior continues by default for backward compatibility.If you want to turn on empty lists for DB static properties, use thewrite_empty_listargument totrue in your Property class; the empty list is then written toDatastore.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.