Datastoreのインデックス定義

KVS(Key-Value Store)のDatstoreではKeyに対してValueが設定されており、クエリの場合、インデックス(Keyの”組み合わせ”)とその結果が常に紐づいているため処理が高速です。
言い換えると、Datastoreはクエリ実行時に常にインデックスを使用しているため、インデックスに紐づかないクエリは実行出来ません。

単純なインデックスは組み込みインデックスと呼ばれ、Datastore構築時にGCPにて自動で定義されますが、複数のKeyを指定しているクエリの場合、それに対応する複合インデックスを定義する必要があります。
対応する複合インデックスが無い状態で検索(クエリ)を行なった場合、サーバーでエラーが発生します。ここでは当該エラーの説明と対処方法を説明します。

以下に公式のリンクを記載しますので、必要に応じてご確認ください。
インデックス
インデックス設定

エラーの詳細

紹介するサンプルの設定について

今回は、TemPlatでプロジェクトを作成した場合に初期に生成されるERDをサンプルとします。

初期のTempuraテーブル

また、通常のNameとPrice指定の検索では組み込みインデックスが適応されてエラーが発生しないので、Priceの検索条件を範囲にして、範囲指定で検索を行っています。

Web画面設定(Priceの検索条件を範囲にしている)
データ管理画面の検索項目

エラーログ

データ管理画面等で対応する複合インデックスが無い状態でクエリを行なった場合、サーバーで以下のようなエラーが発生します。

エラーログ(GCPのロギング画面から確認)

エラーの詳細を書き出すと以下のようになります。

rpc error: code = FailedPrecondition desc = no matching index found. recommended index is:
- kind: Tempura
  properties:
  - name: Name
  - name: Price

エラーの内容を簡単に説明すると、”no matching index found.”の部分が”インデックスが無い状態でクエリを行なった”という意味で、”recommended index is:”の後ろにあるのが、当該クエリで必要なインデックスという意味です。

エラーの対応方法

クエリで必要なインデックスが存在しないことがエラーの原因なので、複合インデックスを定義し、Datastoreへの反映を行うことで対応を行います。

index.yamlの定義

まず、インデックスを定義するにはindex.yamlを作成します。
なお、index.yamlのファイル自体はどこに配置しても問題ありませんが、gitの管理下に置いておくと後ほど更新がしやすくなります。
index.yamlにはエラーログに記載されていたものを記載します。

indexes:

- kind: Tempura
  properties:
  - name: Name
  - name: Price

なお、kindがテーブル名、propertiesがフィールド名で、propertiesは複数指定が可能です。
propertiesには組み合わせで検索を行う可能性のあるフィールドを全て指定する必要があります。
また、propertiesの個別の要素にはdirectionが指定可能で、降順の並び順を指定するpropertiesにはdirectionの指定が必要になります。

例えば、NameとPriceとRecommendedの組み合わせで検索を行い、表示順がPriceの降順の場合は以下のように指定します。

indexes:

- kind: Tempura
  properties:
  - name: Name
  - name: Price
    direction: desc
  - name: Recommended

index.yamlの記載方法は公式サイトでも詳しく説明していますので、そちらも参考にしてください。
index.yamlについて

Datastoreへのindexの反映

Datastoreへインデックスを反映するにはgcloud コマンドライン ツールを使用します。
gcloud ツールを使用するには、Google Cloud SDK のインストールが必要ですので、インストールしていない場合は事前にインストールを行ってください。
Google Cloud SDKのインストール方法

定義したindex.yamlからdatastoreへインデックスを反映するためには以下のコマンドを実行します。
なお、[PROJECT_ID]の部分はご自身のGCPのプロジェクトIDに書き換えて行ってください。

gcloud datastore indexes create --project [PROJECT_ID] index.yaml

インデックスの反映が終わるとGCPから定義したインデックスの確認が出来ます。
ここで確認したインデックスのステータスが”処理しています”になれば、インデックスは有効になっています。
(インデックスの反映には数分かかる場合があります。)

GCPのDatastoreのインデックス一覧画面

クエリを再度実行して、エラーが発生していないことを確認してください。

Datastoreへのindexの更新(削除)

最後に、登録したDatastoreのインデックスの更新方法を説明します。
更新時には作成時と同様にindex.yamlを定義し直したうえで、indexes createコマンドを実行します。

gcloud datastore indexes create --project [PROJECT_ID] index.yaml

ただし、インデックスを更新した場合、新たなインデックスとして登録されてしまいますので、古いインデックスが不要な場合は削除する必要があります。
削除には、indexes cleanupコマンドを使用します。
これにより、index.yamlに定義されていないインデックスを削除することが出来ます。

gcloud datastore indexes cleanup --project [PROJECT_ID] index.yaml