Python NDB/DB の GQL リファレンス

GQL はエンティティやキーを取得するための SQL に似た言語です。GQL クエリの構文は SQL の構文と類似しています。このページでは、Python NDB / DB クライアント ライブラリと GQL を使用する場合について説明します。

GQL はおおむね SQL にマッピングされ、GQL kind は SQL テーブル、GQL entity は SQL 行、GQL property は SQL 列と考えることができます。ただし SQL の行-列ルックアップは単一の値であるのに対し、GQL ではプロパティ値がリストになる場合があります。

GQL バージョン

クエリをどこで実行するかによって、異なるバージョンの GQL が必要になります。次の 2 つの GQL リファレンスがあります。

  • Python NDB/DB 用の GQL リファレンス。NDB と DB クライアント ライブラリで使用される GQL の文法が解説されています(このページでは、リファレンスとして使用します)。

  • GQL リファレンス。現在の Datastore API と Google Cloud Console Datastore Viewer で使用されている GQL の文法が解説されています。

構文

Python NDB/DB の GQL 構文の概要は次のとおりです。

SELECT [DISTINCT] [* | <property list> | __key__]
  [FROM <kind>]
  [WHERE <condition> [AND <condition> ...]]
  [ORDER BY <property> [ASC | DESC] [, <property> [ASC | DESC] ...]]
  [LIMIT [<offset>,]<count>]
  [OFFSET <offset>]

  <property list> := <property> [, <property> ...]
  <condition> := <property> {< | <= | > | >= | = | != } <value>
  <condition> := <property> IN <list>
  <condition> := ANCESTOR IS <entity or key>
  <list> := (<value> [, <value> ...]])

SQL と同様に、GQL キーワードでも大文字と小文字が区別されません。種類とプロパティの名前では大文字と小文字が区別されます。

GQL は SELECT ステートメントのみをサポートします。

GQL クエリは、リクエストされた種類の 0 個以上の完全なエンティティ、射影されたエンティティキーのいずれかを返します。GQL クエリは常に SELECT *SELECT __key__、SELECT <property list> のいずれかで始まります。property は、クエリから取得するエンティティ プロパティのカンマ区切りリストです(GQL クエリでは、SQL のような結合クエリを実行できません)。

ヒント: SELECT __key__ or SELECT <property list> クエリは SELECT * クエリよりも高速で、使用する CPU 時間も短くなります。

オプションの DISTINCT(試験運用版)句を指定すると、完全に一意の結果のみが結果セットで返されます。つまり、プロジェクションされているプロパティについて同じ値を持つエンティティが複数存在する場合は、最初の結果だけが返されます。

オプションの FROM を使用すると、結果セットを特定の種類のエンティティに限定できます。FROM 句のないクエリは「種類を指定しないクエリ」と呼ばれ、__key__ プロパティを指定する WHERE のみを含めることができます。

オプションの WHERE 句は、結果セットを 1 つ以上の条件に合致するエンティティに限定します。それぞれの条件によって、エンティティのプロパティが比較演算子を使用して値と比較されます。AND キーワードを使用して複数の条件を指定すると、すべての条件を満たすエンティティだけがクエリで返されます。GQL に OR 演算子はありません。ただし、IN 演算子を使用すると、制限付きで OR を実行できます。

IN 演算子は、リスト内の各項目のプロパティ値を比較します。IN 演算子は、複数の = クエリ(1 つの値に 1 クエリ)の論理和と同等です。指定したプロパティの値がリスト内の値に一致するエンティティがクエリで返されます。

注: IN 演算子と != 演算子は、バックグラウンドで複数のクエリを使用します。たとえば、IN 演算子は、リストの各項目に対して基盤となるデータストア クエリを実行します。返されたエンティティは基盤となるすべてのデータストア クエリの外積で、重複が除外されます。1 つの GQL クエリで使用可能なデータベース クエリは 30 個までです。

条件に ANCESTOR IS 演算子を使用すると、特定のエンティティに祖先となるエンティティが存在するかどうかテストできます。この値は、祖先エンティティのモデル インスタンスまたはキーになります。祖先の詳細については、キーとエンティティ グループをご確認ください。

比較の左辺は常にプロパティ名になります。一般的なプロパティ名は英数字で構成され、オプションでアンダースコアやドットも使用されます。言い換えれば、正規表現 [a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)* に一致します。

注意: 他の印刷可能な文字を含むプロパティ名は、二重引用符で囲む必要があります。例: "first-name"スペースや印刷不能文字はプロパティ名で使用できません。

比較の右辺はプロパティのデータ型で、次のいずれかになります。

  • str リテラル。単一引用符で囲みます。文字列内で単一引用符を使用するには、'' のようにエスケープする必要があります。例: 'Joe''s Diner'
  • 整数または浮動小数点のリテラル。例: 42.7
  • ブール値のリテラル。TRUE または FALSE
  • NULL リテラル。null 値を表します(Python では None)。
  • 日時、日付または時間のリテラル。次のような数値または文字列表現になります。
    • DATETIME(year, month, day, hour, minute, second)
    • DATETIME('YYYY-MM-DD HH:MM:SS')
    • DATE(year, month, day)
    • DATE('YYYY-MM-DD')
    • TIME(hour, minute, second)
    • TIME('HH:MM:SS')
  • エンティティ キーのリテラル。文字列でエンコードされたキーまたは種類とキー名 / ID で構成される完全なパス:

    • KEY('encoded key')
    • KEY('kind', 'name'/ID [, 'kind', 'name'/ID...])
  • USER オブジェクト リテラル。ユーザーのメールアドレスが含まれます。
    USER('email-address')
  • GeoPt のリテラル。緯度経度を表す浮動小数点。
    GEOPT(lat, long)
  • バインドされたパラメータ値。クエリ文字列で、位置パラメータは数字 title = :1 で参照されます。キーワード パラメータは名前 title = :mytitle で参照されます。

注: property = NULL 形式の条件は、このプロパティのデータストアに null 値が明示的に格納されているかどうかを検査します。これは、エンティティのプロパティの値が存在しないかどうかの検査とは異なります。プロパティを参照するデータストア クエリでは、そのプロパティに値のないエンティティは返されません。

バインドされたパラメータは、GqlQuery コンストラクタまたはモデルクラスの gql() メソッドに渡される位置引数またはキーワード引数としてバインドされます。対応する値リテラルの構文がないプロパティ データタイプは、パラメータをバインドして指定し、リスト データタイプを追加する必要があります。パラメータのバインドは、GqlQuery インスタンスの存続期間中、(たとえばクエリを効果的に再利用するために)bind() メソッドを使用して新しい値で再度バインドできます。

オプションの ORDER BY 句は、返された結果を指定プロパティの昇順(ASC)または降順(DESC)で並べ替えることを表します。ORDER BY 句では複数の並べ替え順序を、左から右へ評価されるカンマ区切りリストとして指定できます。順序が指定されていない場合は、ASC がデフォルトです。ORDER BY 句を指定しなかった場合、結果の順序は定義されず、時間が経つと変化することがあります。

オプションの LIMIT 句を使用すると、最初の <count> エンティティの後で結果の送信を停止できます。また、LIMIT 句で <offset> を追加すると、最初の結果を返すまでにスキップする結果数を指定できます。LIMIT 句を使用しない場合、オプションの OFFSET 句で <offset> を指定できます。

注: fetch() メソッドの offset パラメータと同様に、GQL クエリ文字列で OFFSET を使用しても、データストアからフェッチされるエンティティの数は減りません。fetch() メソッドが返す結果に影響を及ぼすだけです。クエリでオフセットを指定すると、オフセット サイズと制限サイズを使用した場合と類似した効果があります。

GQL クエリの実行、パラメータのバインド、結果へのアクセス方法については、GqlQuery クラスと Model.gql() クラスメソッドをご覧ください。

from google.appengine.ext import db

class Person(db.Model):
  name = db.StringProperty()
  age = db.IntegerProperty()

# We use a unique username for the Entity's key.
amy = Person(key_name='amym', name='Amy', age=48)
amy.put()
Person(key_name='bettyd', name='Betty', age=42).put()
Person(key_name='charliec', name='Charlie', age=32).put()
Person(key_name='charliek', name='Charlie', age=29).put()
Person(key_name='eedna', name='Edna', age=20).put()
Person(key_name='fredm', name='Fred', age=16, parent=amy).put()
Person(key_name='georgemichael', name='George').put()

種類が Person で年齢が 18~35 のエンティティ(ここでは、Charlies と Edna)をすべて検索する場合は、次のクエリを使用します。

SELECT * FROM Person WHERE age >= 18 AND age <= 35

種類が Person で年齢が最も大きい 3 つのエンティティ(ここでは、Amy、Betty、Charlie)を検索するには、次のクエリを使用します。

SELECT * FROM Person ORDER BY age DESC LIMIT 3

種類が Person で、名前が Betty または Charlie のいずれかのエンティティを検索するには、次のクエリを使用します。

SELECT * FROM Person WHERE name IN ('Betty', 'Charlie')

Personname 値のみを返すには、次のクエリを使用します。

SELECT name FROM Person

それぞれの Personname 値だけを age の順序で返すには、次のクエリを使用します。

SELECT name FROM Person ORDER BY age

種類が Person で年齢が None のエンティティ(例: KEY('Person', 'georgemichael'))のキーを検索するには、次のクエリを使用します。

SELECT __key__ FROM Person WHERE age = NULL

種類にかかわらず、Amy のエンティティ グループ(Amy と Fred)にあるエンティティをすべて検索する場合は、次のクエリを使用します。

SELECT * WHERE __key__ HAS ANCESTOR KEY(Person, 'Amy')

キーで指定するには、条件の左辺で __key__ を使用します。たとえば、ユーザー名が "a" で始まる Person エンティティをすべて取得するには、次のクエリを使用します。

SELECT * FROM Person WHERE __key__ >= KEY('Person', 'a') AND __key__ < KEY('Person', 'b')

注: __key__ で等式を含むクエリを作成する場合は、代わりに get() を使用してエンティティを直接フェッチすることを検討してください。