Entity Property Reference

Firestore in Datastore mode (Datastore) supports a variety of data types for property values. These include, among others:

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

For a full list of types, see Properties and value types.

Properties and value types

The data values associated with an entity consist of one or more properties. 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 property P will ignore entities where P is unindexed). An entity can have at most 20,000 indexed properties.

The following value types are supported:

Value type Java type(s) Sort order Notes
Integer short
int
long
java.lang.Short
java.lang.Integer
java.lang.Long
Numeric Stored as long integer, then converted to the field type

Out-of-range values overflow
Floating-point number float
double
java.lang.Float
java.lang.Double
Numeric 64-bit double precision,
IEEE 754
Boolean boolean
java.lang.Boolean
false<true
Text string (short) java.lang.String Unicode Up to 1500 bytes

Values greater than 1500 bytes throw IllegalArgumentException
Text string (long) com.google.appengine.api.datastore.Text None Up to 1 megabyte

Not indexed
Byte string (short) com.google.appengine.api.datastore.ShortBlob Byte order Up to 1500 bytes

Values longer than 1500 bytes throw IllegalArgumentException
Byte string (long) com.google.appengine.api.datastore.Blob None Up to 1 megabyte

Not indexed
Date and time java.util.Date Chronological
Geographical point com.google.appengine.api.datastore.GeoPt By latitude,
then longitude
Postal address com.google.appengine.api.datastore.PostalAddress Unicode
Telephone number com.google.appengine.api.datastore.PhoneNumber Unicode
Email address com.google.appengine.api.datastore.Email Unicode
Google Accounts user com.google.appengine.api.users.User Email address
in Unicode order
Instant messaging handle com.google.appengine.api.datastore.IMHandle Unicode
Link com.google.appengine.api.datastore.Link Unicode
Category com.google.appengine.api.datastore.Category Unicode
Rating com.google.appengine.api.datastore.Rating Numeric
Datastore key com.google.appengine.api.datastore.Key
or the referenced object (as a child)
By path elements
(kind, identifier,
kind, identifier...)
Up to 1500 bytes

Values longer than 1500 bytes throw IllegalArgumentException
Blobstore key com.google.appengine.api.blobstore.BlobKey Byte order
Embedded entity com.google.appengine.api.datastore.EmbeddedEntity None Not indexed
Null null None

Important: We strongly recommend that you avoid storing a users.User as a property value, because this includes the email address along with the unique ID. If a user changes their email address and you compare their old, stored user.User to the new user.User value, they won't match. Instead, use the User user ID value as the user's stable unique identifier.

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 named Blob in the Datastore API. This type is unrelated to blobs as used in the Blobstore 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, long byte strings, and embedded entities are not indexed, they have no ordering defined.

Repeated properties

You can store multiple values within a single property.

Entity employee = new Entity("Employee");
ArrayList<String> favoriteFruit = new ArrayList<String>();
favoriteFruit.add("Pear");
favoriteFruit.add("Apple");
employee.setProperty("favoriteFruit", favoriteFruit);
datastore.put(employee);

// Sometime later
employee = datastore.get(employee.getKey());
@SuppressWarnings("unchecked") // Cast can't verify generic type.
    ArrayList<String> retrievedFruits = (ArrayList<String>) employee
    .getProperty("favoriteFruit");

Embedded entities

You may sometimes find it convenient to embed one entity as a property of another entity. This can be useful, for instance, for creating a hierarchical structure of property values within an entity. The Java class EmbeddedEntity allows you to do this:

// Entity employee = ...;
EmbeddedEntity embeddedContactInfo = new EmbeddedEntity();

embeddedContactInfo.setProperty("homeAddress", "123 Fake St, Made, UP 45678");
embeddedContactInfo.setProperty("phoneNumber", "555-555-5555");
embeddedContactInfo.setProperty("emailAddress", "test@example.com");

employee.setProperty("contactInfo", embeddedContactInfo);

Properties of an embedded entity are not indexed and cannot be used in queries. You can optionally associate a key with an embedded entity, but (unlike a full-fledged entity) the key is not required and, even if present, cannot be used to retrieve the entity.

Instead of populating the embedded entity's properties manually, you can use the setPropertiesFrom() method to copy them from an existing entity:

// Entity employee = ...;
// Entity contactInfo = ...;
EmbeddedEntity embeddedContactInfo = new EmbeddedEntity();

embeddedContactInfo.setKey(contactInfo.getKey()); // Optional, used so we can recover original.
embeddedContactInfo.setPropertiesFrom(contactInfo);

employee.setProperty("contactInfo", embeddedContactInfo);

You can later use the same method to recover the original entity from the embedded entity:

Entity employee = datastore.get(employeeKey);
EmbeddedEntity embeddedContactInfo = (EmbeddedEntity) employee.getProperty("contactInfo");

Key infoKey = embeddedContactInfo.getKey();
Entity contactInfo = new Entity(infoKey);
contactInfo.setPropertiesFrom(embeddedContactInfo);

Using an empty list

Datastore historically did not have a representation for a property representing an empty list. The Java SDK worked around this by storing empty collections as null values, so there is no way to distinguish between null values and empty lists. To maintain backward compatibility, this remains the default behavior, synopsized as follows:

  • Null properties are written as null to Datastore
  • Empty collections are written as null to Datastore
  • A null is read as null from Datastore
  • An empty collection is read as null.

However, if you change the default behavior, the Appengine Datastore Java SDK will support storage of empty lists. We recommend you consider the implications of changing the default behavior of your application and then turn on support for empty lists.

To change default behavior so you can use empty lists, set the DATASTORE_EMPTY_LIST_SUPPORT property during your app initialization as follows:

System.setProperty(DatastoreServiceConfig.DATASTORE_EMPTY_LIST_SUPPORT, Boolean.TRUE.toString());

With this property set to true as shown above:

  • Null properties are written as null to Datastore
  • Empty collections are written as an empty list to Datastore
  • A null is read as null from Datastore
  • When reading from Datastore an empty list is returned as an empty Collection.