Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)



Using GQL

GQL is a SQL-like language for retrieving entities or keys from Datastore. While GQL's features are different from those of a query language for a traditional relational database, the GQL grammar is similar to that of SQL.

GQL reference

This page describes building a GQL query, which consists of a GQL query string along with optional named and/or numbered arguments.

For details on the GQL query string itself, you need to see the GQL reference page.

Building a GQL query

The following code snippet shows how to construct and send a simple GQL query:

Node.js (JSON)

function gqlExample(callback) {
  datastore.runQuery({
    gqlQuery: {
      queryString: 'SELECT * FROM Person',
    }
  }).execute(function(err, result) {
    if (!err) {
      // Iterate over the results and return the entities.
      result = (result.batch.entityResults || []).map(
        function(entityResult) {
          return entityResult.entity;
        });
    }
    callback(err, result);
  });
}

Python (Protocol Buffers)

req = datastore.RunQueryRequest()
gql_query = req.gql_query

gql_query.query_string = 'SELECT * FROM Person'

resp = self.datastore.run_query(req)
results = [entity_result.entity
           for entity_result in resp.batch.entity_result]

Java (Protocol Buffers)

// import static com.google.apphosting.client.datastoreservice.client.DatastoreHelper.*;

GqlQuery.Builder query = GqlQuery.newBuilder().setQueryString("SELECT * FROM Person");
RunQueryRequest request = RunQueryRequest.newBuilder().setGqlQuery(query).build();

RunQueryResponse response = datastore.runQuery(request);
List<Entity> results = new ArrayList<Entity>();
for (EntityResult entityResult : response.getBatch().getEntityResultList()) {
  results.add(entityResult.getEntity());
}

Tips about GQL behavior

The following table highlights some important aspects of GQL literal values and operators:

Behavior Example
An integer value is not equal to the equivalent double: for example 7 is not equal to 7.0 SELECT * WHERE i = 7.0 will never yield an entity with single-valued property i with value 7 ; SELECT * WHERE d = 7 will never yield an entity with single-valued property d with value 7.0 .
Null is a value, not the absence of a value. There is no way to determine whether an entity lacks a value for a property (that is, whether the property has no value). If you use a condition of the form property = NULL , what will occur is a check whether a null value is explicitly stored for that property. For example, SELECT * WHERE p = NULL will never yield an entity with 0 values for property p .
A + immediately followed by an integer literal without a sign, for example +17 , is always interpreted as an explicitly positive integer, and never as a + and an implicitly positive integer. When the latter interpretation is desired, include whitespace between the + and the integer literal.
  • OFFSET @cursor + 17 is valid
  • OFFSET @cursor + +17 is valid
  • OFFSET @cursor +17 is invalid
The operator = functions like the IN or CONTAINS operators, which can yield some surprising results, especially when used with multi-valued properties. SELECT * WHERE p = 3 AND p = 7 might be expected never to yield any entities, but it is interpreted as SELECT * WHERE p CONTAINS 3 AND p CONTAINS 7 which may certainly yield entities.

Argument binding

Argument binding provide a way for users to specify a value at runtime while at the same time preventing malicious behavior, such as injection attacks.

To specify an argument binding, you specify a binding argument/value pair, similar to this:

Argument Value
aVal 13
bVal trisky

The way you actually do this varies by language, so refer to the argument binding code snippets below for details.

The query string uses binding sites to refer to the above bound argument values, using @ . For example:

    SELECT * WHERE a = @aVal AND b = @bVal

At execution time, this yields SELECT * WHERE a = 13 AND b = 'trisky'

There are a few usage considerations to keep in mind:

  • Any name may be used as a binding site name, although keywords and predefined name should be avoided; names with leading/trailing double underscore ( __foo__ ) are permitted. However, names for an argument binding cannot use names with leading/trailing double underscore.
  • A given name or number may be used in multiple argument binding sites in a single query string.
  • A query that contains a numbered argument binding site cannot skip any numbers: for example if you have an argument binding @2 , you must also have the argument binding @1 ; if you have a argument binding @3 , you must also have the argument bindings @1 and @2 , and so forth. You don't have to use them in any particular order, but they must all be present.

Argument binding sample

The following snippets shows how to use argument binding with named arguments:

Node.js (JSON)

function gqlNamedArgsExample(callback) {
  datastore.runQuery({
    gqlQuery: {
      queryString: 'SELECT * FROM Person WHERE height >= @minHeight AND height <= @maxHeight',
      nameArgs: [{ name: 'minHeight', value: { integerValue: 48 } },
                 { name: 'maxHeight', value: { integerValue: 60 } }]
    }
  }).execute(function(err, result) {
    if (!err) {
      // Iterate over the results and return the entities.
      result = (result.batch.entityResults || []).map(
        function(entityResult) {
          return entityResult.entity;
        });
    }
    callback(err, result);
  });
}

Python (Protocol Buffers)

req = datastore.RunQueryRequest()
gql_query = req.gql_query

query_string = ('SELECT * FROM Person WHERE height >= @minHeight '
                'AND height <= @maxHeight')
gql_query.query_string = query_string

query_arg = gql_query.name_arg.add()
query_arg.name = 'minHeight'
query_arg.value.integer_value = 48

query_arg = gql_query.name_arg.add()
query_arg.name = 'maxHeight'
query_arg.value.integer_value = 60

resp = self.datastore.run_query(req)
results = [entity_result.entity
           for entity_result in resp.batch.entity_result]

Java (Protocol Buffers)

// import static com.google.apphosting.client.datastoreservice.client.DatastoreHelper.*;

GqlQuery.Builder query = GqlQuery.newBuilder()
    .setQueryString("SELECT * FROM Person WHERE height >= @minHeight AND height <= @maxHeight");
query.addNameArgBuilder().setName("minHeight").setValue(makeValue(48));
query.addNameArgBuilder().setName("maxHeight").setValue(makeValue(60));
RunQueryRequest request = RunQueryRequest.newBuilder().setGqlQuery(query).build();

RunQueryResponse response = datastore.runQuery(request);
List<Entity> results = new ArrayList<Entity>();
for (EntityResult entityResult : response.getBatch().getEntityResultList()) {
  results.add(entityResult.getEntity());
}

The following snippets shows how to use argument binding with numbered arguments:

Node.js (JSON)

function gqlNumberedArgsExample(callback) {
  datastore.runQuery({
    gqlQuery: {
      queryString: 'SELECT * FROM Person WHERE height >= @1 AND height <= @2',
      numberArgs: [{ value: { integerValue: 48 } },
                   { value: { integerValue: 60 } }]
    }
  }).execute(function(err, result) {
    if (!err) {
      // Iterate over the results and return the entities.
      result = (result.batch.entityResults || []).map(
        function(entityResult) {
          return entityResult.entity;
        });
    }
    callback(err, result);
  });
}

Python (Protocol Buffers)

req = datastore.RunQueryRequest()
gql_query = req.gql_query

query_string = 'SELECT * FROM Person WHERE height >= @1 AND height <= @2'
gql_query.query_string = query_string
gql_query.number_arg.add().value.integer_value = 48
gql_query.number_arg.add().value.integer_value = 60

resp = self.datastore.run_query(req)
results = [entity_result.entity
           for entity_result in resp.batch.entity_result]

Java (Protocol Buffers)

// import static com.google.apphosting.client.datastoreservice.client.DatastoreHelper.*;

GqlQuery.Builder query = GqlQuery.newBuilder()
    .setQueryString("SELECT * FROM Person WHERE height >= @1 AND height <= @2");
query.addNumberArgBuilder().setValue(makeValue(48));
query.addNumberArgBuilder().setValue(makeValue(60));
RunQueryRequest request = RunQueryRequest.newBuilder().setGqlQuery(query).build();

RunQueryResponse response = datastore.runQuery(request);
List<Entity> results = new ArrayList<Entity>();
for (EntityResult entityResult : response.getBatch().getEntityResultList()) {
  results.add(entityResult.getEntity());
}

Using literals sample code

The following snippet shows the use of literals:

Node.js (JSON)

function gqlLiteralExample(callback) {
  datastore.runQuery({
    gqlQuery: {
      queryString: 'SELECT * FROM Person WHERE height >= 48 AND height <= 60',
      allowLiteral: true
    }
  }).execute(function(err, result) {
    if (!err) {
      // Iterate over the results and return the entities.
      result = (result.batch.entityResults || []).map(
        function(entityResult) {
          return entityResult.entity;
        });
    }
    callback(err, result);
  });
}

Python (Protocol Buffers)

req = datastore.RunQueryRequest()
gql_query = req.gql_query

query_string = 'SELECT * FROM Person WHERE height >= 48 AND height <= 60'
gql_query.query_string = query_string
gql_query.allow_literal = True

resp = self.datastore.run_query(req)
results = [entity_result.entity
           for entity_result in resp.batch.entity_result]

Java (Protocol Buffers)

// import static com.google.apphosting.client.datastoreservice.client.DatastoreHelper.*;

GqlQuery.Builder query = GqlQuery.newBuilder()
    .setQueryString("SELECT * FROM Person WHERE height >= 48 AND height <= 60");
query.setAllowLiteral(true);
RunQueryRequest request = RunQueryRequest.newBuilder().setGqlQuery(query).build();

RunQueryResponse response = datastore.runQuery(request);
List<Entity> results = new ArrayList<Entity>();
for (EntityResult entityResult : response.getBatch().getEntityResultList()) {
  results.add(entityResult.getEntity());
}

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.