インデックス

Google Cloud Datastore のすべてのクエリは、1 つ以上のインデックスを使用して結果を計算します。インデックスには、インデックスのプロパティとエンティティの祖先(オプション)によって指定された順序でエンティティのキーが格納されています。インデックスは、アプリケーションがエンティティに加えた変更を反映して更新されます。そのため追加の計算を行うことなく、すべてのクエリの正しい結果が得られます。

インデックスは次の 2 種類に分けられます。

組み込みインデックス
デフォルトでは、エンティティの種類ごとに各プロパティのインデックスが自動的に事前定義されます。このような単一プロパティのインデックスは単純な種類のクエリに適しています。
複合インデックス
複合インデックスでは、インデックス付けされたエンティティごとに複数のプロパティ値がインデックス付けされます。複雑なクエリをサポートする複合インデックスは、インデックス設定ファイルindex.yaml)で定義されます。

インデックスの種類については、このトピックの後半で詳しく説明します。

インデックスとクエリの深い議論については、インデックスの選択と高度な検索をご覧ください。

インデックスの定義と構造

インデックスは、特定の種類のエンティティのプロパティを、各プロパティの対応する順序(昇順または降順)で並べたリストに対して定義されます。また祖先クエリで使用できるように、オプションでエンティティの祖先を含めることもできます。

インデックス テーブルには、インデックスの定義で指定されたすべてのプロパティに対応する列が含まれています。テーブルの各行は Cloud Datastore 内のエンティティを表し、これがインデックスに基づくクエリの結果となります。インデックスには、インデックスで使用されているすべてのプロパティに対応するインデックス付けされた値セットを持つエンティティのみが含められます。インデックス定義で参照されているプロパティに対応する値を持たないエンティティはインデックスに含まれないため、インデックスに基づくクエリで結果として返されることはありません。

インデックス テーブルの行は祖先の次にプロパティ値という順序で並べ替えられますが、各プロパティ値はインデックス定義で指定された順序になります。クエリを最も効率的に実行できる「完璧なインデックス」とは、次のプロパティをこの順序で定義したものです。

  1. 等式フィルタで使用されるプロパティ
  2. 不等式フィルタ(プロパティを 1 つしか使用しないもの)で使用されるプロパティ
  3. 並べ替えの順序で使用されるプロパティ

これにより、実行される可能性があるすべてのクエリの結果が、テーブルの連続した行として表れます。Cloud Datastore は、次のステップに従って完璧なインデックスを使用し、クエリを実行します。

  1. クエリの種類、フィルタのプロパティ、フィルタの演算子、並べ替えの順序に対応するインデックスを特定します。
  2. インデックスの先頭からクエリのフィルタ条件をすべて満たす最初のエンティティまでスキャンします。
  3. インデックスのスキャンを続行し、各エンティティを返します。スキャンは、次の条件のいずれかが満たされるまで続けられます。
    • フィルタ条件を満たさないエンティティを検出する
    • インデックスの末尾に到達する
    • クエリでリクエストされた結果の最大数に達した

たとえば、次のクエリについて考えてみます。

SELECT * FROM Task
WHERE category = 'Personal'
  AND priority < 3
ORDER BY priority DESC

このクエリの完璧なインデックスは、種類 Task のエンティティのキーを含むテーブルで、テーブルの列に categorypriority プロパティの値が含まれます。インデックスはまず category の昇順、次に priority の降順で並べ替えられています。

indexes:
- kind: Task
  properties:
  - name: category
    direction: asc
  - name: priority
    direction: desc

形式が同じでフィルタの値が異なる 2 つのクエリは、同じインデックスを使用します。たとえば、次のクエリは上記の例と同じインデックスを使用します。

SELECT * FROM Task
WHERE category = 'Work'
  AND priority < 5
ORDER BY priority DESC

次のインデックスについては、

indexes:
- kind: Task
  properties:
  - name: category
    direction: asc
  - name: priority
    direction: asc
  - name: created
    direction: asc

形式が異なるにもかかわらず、次の 2 つのクエリでも同じインデックスを使用します。

SELECT * FROM Task
WHERE category = 'Personal'
  AND priority = 5
ORDER BY created ASC

および

SELECT * FROM Task
WHERE category = 'Work'
ORDER BY priority ASC, created ASC

上記の例で作成したインデックスは、どちらのクエリも満たすことができます。

インデックスの設定

Cloud Datastore では組み込みインデックス、つまり次の形式のクエリに適した自動的なインデックスが提供されます。

  • 祖先フィルタとキーフィルタだけを使用した種類のないクエリ
  • 祖先フィルタと等式フィルタだけを使用したクエリ
  • 不等式フィルタ(プロパティを 1 つしか使用しないもの)だけを使用したクエリ
  • 祖先フィルタ、プロパティに対する等式フィルタ、キーに対する不等式フィルタだけを使用したクエリ
  • フィルタがなく、プロパティに対する並べ替え順序が昇順か降順のいずれかだけのクエリ

たとえば Cloud Datastore はデフォルトで、各エンティティの種類のプロパティごとに 2 つの単一プロパティ インデックスを自動的に事前定義します。1 つは昇順で、もう 1 つは降順になります。プロパティのインデックスを保持する必要がない場合は、インデックスからプロパティを除外します。ただしプロパティを除外すると、複合インデックスからも削除される点に注意してください。

組み込みインデックスは、等式だけのクエリや単純な不等式クエリなど、多くの単純なクエリを実行するのに十分です。

組み込みインデックスは、Google Cloud Platform Console のインデックス ページには表示されません。

複雑なクエリの場合は複合インデックス、つまり手動のインデックスを定義する必要があります。複合インデックスは、次の形式のクエリで必要になります。

  • 祖先フィルタと不等式フィルタを持つクエリ
  • 1 つのプロパティに対して 1 つ以上の不等式フィルタを使用し、他のプロパティに対して 1 つ以上の等式フィルタを使用したクエリ
  • キーの降順という並べ替え順序を使用したクエリ
  • 複数の並べ替え順序を持つクエリ
  • 1 つ以上のフィルタと並べ替え順序を持つクエリ

複合インデックスはアプリケーションのインデックス設定ファイルindex.yaml)で定義されます(組み込みインデックスはインデックス設定ファイルに含まれていません)。

複合インデックスは複数のプロパティで構成されており、個々のプロパティがインデックスから除外されていてはなりません。

複合インデックスは、GCP Console のインデックス ページで確認できます。GCP Console を使用して複合インデックスを作成または更新することはできません。

使用可能なインデックス(組み込みインデックスまたはインデックス設定ファイルで指定されているインデックス)を使って実行できないクエリをアプリケーションが実行しようとすると、そのクエリは失敗します。

Cloud Datastore API は、ほとんどのアプリケーションに適したインデックスを自動的に提示します。ただしアプリケーションでの Cloud Datastore の使用方法とデータのサイズと形状によっては、インデックスを手動で調整したほうが動作が確実になる場合があります。たとえば、複数のプロパティ値を持つエンティティを書き込むとインデックス爆発が発生し、ストレージ コストが高くなる可能性があります。

Cloud Datastore エミュレータを使用すると、インデックス設定ファイルを簡単に管理できます。必要なインデックスが存在しない状態でクエリを実行すると失敗しますが、Cloud Datastore エミュレータを使用すればクエリの実行が成功するようにインデックス設定を生成できます。アプリケーションのローカルテストで、フィルタや並べ替え順のすべての組み合わせを使用して、アプリケーションが発行する可能性のあるすべてのクエリが試行されている場合、生成されるエントリはインデックスの完全なセットを表すことになります。テストで可能性のあるすべての形式のクエリが試行されない場合は、インデックスを更新する前にインデックス設定ファイルを確認、調整できます。

index.yaml の詳細については、インデックスの設定をご覧ください。

インデックスのデプロイ、削除

インデックス構成ファイルの変更が完了したら、gcloud datastore create-indexes コマンドを実行してインデックスの使用を開始します。詳細については、インデックスの更新をご覧ください。

以前にデプロイしたインデックスが不要になった場合は、使われていないインデックスを削除できます。

インデックスとプロパティ

ここでは、インデックスについて特に考慮すべきことと、インデックスを Cloud Datastore 内のエンティティのプロパティにどのように関連付けるかに関して留意しなければならないことを説明します。

値の型が混在するプロパティ

2 つのエンティティに名前が同じで値の型が異なるプロパティが存在する場合、プロパティのインデックスはまず値の型でエンティティを並べ替え、次に各型に対して適切な順序で並べ替えを行います。たとえば 2 つのエンティティそれぞれに age という名前のプロパティが存在し、一方が整数値を持つプロパティで、もう一方が文字列値を持つプロパティの場合、age プロパティを基準とした並べ替えを行うと、プロパティの値自体には関係なく常に整数値を持つエンティティのほうが文字列値を持つエンティティよりも順序が先になります。

Cloud Datastore では整数値と浮動小数点型の数値が別の型として区別されるため、このような動作について特に注意する必要があります。すべての整数値はすべての浮動小数点型の数値よりも順序が前になるため、整数値 38 を持つプロパティは浮動小数点値 37.5 を持つプロパティよりも前になります。

除外されたプロパティ

特定のプロパティに対するフィルタリングや並べ替えが不要な場合は、インデックスから除外することで、そのプロパティのインデックス エントリが保持されなくなります。これによりインデックス エントリの保持に必要な分だけストレージ サイズが低減されるため、アプリケーションの実行にかかるコストが低く抑えられます。除外されたプロパティを持つエンティティは、そのプロパティが設定されていないかのように振る舞います。除外されたプロパティに対するフィルタまたは並べ替え順を持つクエリが、そのエンティティに一致することはありません。

次の例の description プロパティは、インデックスから除外されています。

C#

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["category"] = "Personal",
    ["created"] = new DateTime(1999, 01, 01, 0, 0, 0, DateTimeKind.Utc),
    ["done"] = false,
    ["priority"] = 4,
    ["percent_complete"] = 10.0,
    ["description"] = new Value()
    {
        StringValue = "Learn Cloud Datastore",
        ExcludeFromIndexes = true
    },
};

Go

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

type Task struct {
	Category        string
	Done            bool
	Priority        int
	Description     string `datastore:",noindex"`
	PercentComplete float64
	Created         time.Time
}
task := &Task{
	Category:        "Personal",
	Done:            false,
	Priority:        4,
	Description:     "Learn Cloud Datastore",
	PercentComplete: 10.0,
	Created:         time.Now(),
}

Java

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

Entity task = Entity.newBuilder(taskKey)
    .set("category", "Personal")
    .set("created", Timestamp.now())
    .set("done", false)
    .set("priority", 4)
    .set("percent_complete", 10.0)
    .set("description",
      StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build())
    .build();

Node.js

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

const task = [
  {
    name: 'category',
    value: 'Personal',
  },
  {
    name: 'created',
    value: new Date(),
  },
  {
    name: 'done',
    value: false,
  },
  {
    name: 'priority',
    value: 4,
  },
  {
    name: 'percent_complete',
    value: 10.0,
  },
  {
    name: 'description',
    value: 'Learn Cloud Datastore',
    excludeFromIndexes: true,
  },
];

PHP

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

$task = $datastore->entity(
    $key,
    [
        'category' => 'Personal',
        'created' => new DateTime(),
        'done' => false,
        'priority' => 4,
        'percent_complete' => 10.0,
        'description' => 'Learn Cloud Datastore'
    ],
    ['excludeFromIndexes' => ['description']]
);

Python

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

task = datastore.Entity(
    key,
    exclude_from_indexes=['description'])
task.update({
    'category': 'Personal',
    'description': 'Learn Cloud Datastore',
    'created': datetime.datetime.utcnow(),
    'done': False,
    'priority': 4,
    'percent_complete': 10.5,
})

Ruby

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

task = datastore.entity "Task" do |t|
  t["category"] = "Personal"
  t["created"] = Time.now
  t["done"] = false
  t["priority"] = 4
  t["percent_complete"] = 10.0
  t["description"] = "Learn Cloud Datastore"
  t.exclude_from_indexes! "description", true
end

GQL

該当なし

description プロパティが除外されている場合、次の例のクエリは結果を一切返しません。

C#

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

Query query = new Query("Task")
{
    Filter = Filter.Equal("description", "Learn Cloud Datastore")
};

Go

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

query := datastore.NewQuery("Tasks").Filter("Description =", "A task description")

Java

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

Query<Entity> query = Query.newEntityQueryBuilder()
    .setKind("Task")
    .setFilter(PropertyFilter.eq("description", "A task description"))
    .build();

Node.js

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

const query = datastore
  .createQuery('Task')
  .filter('description', '=', 'A task description.');

PHP

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

$query = $datastore->query()
    ->kind('Task')
    ->filter('description', '=', 'A task description.');

Python

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

query = client.query(kind='Task')
query.add_filter('description', '=', 'Learn Cloud Datastore')

Ruby

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

query = datastore.query("Task").
        where("description", "=", "A task description.")

GQL


# Will not return any results!
SELECT * FROM Task WHERE description = 'A task description.'

後でプロパティを変更して再度インデックス付けできます。

ただし、除外されているプロパティを変更してインデックス付けした場合でも、変更前に作成された既存のエンティティには影響しない点に注意してください。このようなプロパティに対してフィルタリングを行うクエリは、これらの既存のエンティティを返しません。これは、既存エンティティの作成時にクエリのインデックスに書き込まれていなかったためです。このようなエンティティに今後実行するクエリでアクセスできるようにするには、Cloud Datastore にエンティティを書き込み直して適切なインデックスに含まれるようにする必要があります。つまり、既存のエンティティについては次の手順を行う必要があります。

  1. Cloud Datastore からエンティティを検索します(get)。
  2. Cloud Datastore にエンティティを書き込みます(put)。

同様に、インデックス付けされているプロパティを変更してインデックスから除外した場合も、変更後に Cloud Datastore に書き込まれたエンティティにしか影響しません。そのプロパティを持つ既存のエンティティのインデックス エントリは、エンティティが更新または削除されるまで存在し続けます。目的に合わない結果を回避するには、そのような(現在は除外されている)プロパティを基準としてフィルタリングや並べ替えを行うすべてのクエリのコードを消去する必要があります。

インデックスの制限

Cloud Datastore では、単一のエンティティに関連付けられるインデックス エントリの数と合計サイズについて制限が課されています。これらの制限は十分な余裕があるため、ほとんどのアプリケーションは影響を受けません。ただし、場合によっては制限に達することもあります。

上記で説明したように、Cloud Datastore はすべてのエンティティのすべてのプロパティについて、事前定義されたインデックスにエントリを作成します。ただし、インデックスから除外することを明示的に宣言したものは除きます。また、インデックス設定ファイルindex.yaml)で宣言した追加のカスタム インデックスにプロパティを含めることもできます。エンティティにリスト プロパティが存在しない場合、そのようなエンティティはカスタム インデックスごとに最大で 1 つのエントリ(非祖先インデックスの場合)、またはエンティティの祖先ごとに 1 つのエントリ(祖先インデックスの場合)を持つことになります。このようなインデックス エントリは、プロパティの値が変化するたびに更新しなければなりません。

エンティティごとに 1 つの値を持つプロパティについては、そのプロパティの事前定義インデックスにエンティティごとに値を 1 回保存するだけで済みます。ただし、そのような単一値のプロパティを大量に持つエンティティの場合は、インデックスのエントリ数またはサイズの制限を超過する可能性があります。同様に、同じプロパティに対して複数の値を持つエンティティは値ごとに個別のインデックス エントリが必要になるため、値の数が大量に存在する場合は、やはりエントリの制限を超過する可能性があります。

複数のプロパティが存在するエンティティで、それぞれのプロパティが複数の値を取る場合、状況はさらに悪化します。そのようなエンティティに対処するには、可能性のあるすべてのプロパティ値の組み合わせに対応するエントリをインデックスに含める必要があります。カスタム インデックスが複数のプロパティを参照し、それぞれのプロパティが複数の値を持つ場合、組み合わせ数が爆発的に増加する可能性があり、比較的少数のプロパティ値しか持たないエンティティのエントリが大量に必要になります。このような「インデックス爆発」により大量のインデックス エントリを格納しなければならなくなるため、Cloud Datastore のエンティティのストレージ サイズが大幅に増加する場合があります。またインデックス爆発は、インデックスのエントリ数またはサイズの制限を超過する原因となりやすい状況でもあります。

たとえば、次のようなコードについて考えてみましょう。

C#

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["tags"] = new ArrayValue() { Values = { "fun", "programming", "learn" } },
    ["collaborators"] = new ArrayValue() { Values = { "alice", "bob", "charlie" } },
    ["created"] = DateTime.UtcNow
};

Go

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

task := &Task{
	Tags:          []string{"fun", "programming", "learn"},
	Collaborators: []string{"alice", "bob", "charlie"},
	Created:       time.Now(),
}

Java

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

Entity task = Entity.newBuilder(taskKey)
    .set("tags", "fun", "programming", "learn")
    .set("collaborators", "alice", "bob", "charlie")
    .set("created", Timestamp.now())
    .build();

Node.js

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

const task = {
  method: 'insert',
  key: datastore.key('Task'),
  data: {
    tags: ['fun', 'programming', 'learn'],
    collaborators: ['alice', 'bob', 'charlie'],
    created: new Date(),
  },
};

PHP

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

$task = $datastore->entity(
    $datastore->key('Task'),
    [
        'tags' => ['fun', 'programming', 'learn'],
        'collaborators' => ['alice', 'bob', 'charlie'],
        'created' => new DateTime(),
    ]
);

Python

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

task = datastore.Entity(client.key('Task'))
task.update({
    'tags': [
        'fun',
        'programming',
        'learn'
    ],
    'collaborators': [
        'alice',
        'bob',
        'charlie'
    ],
    'created': datetime.datetime.utcnow()
})

Ruby

Cloud Datastore クライアントのインストールと作成の詳細については、Cloud Datastore クライアント ライブラリをご覧ください。

task = datastore.entity "Task" do |t|
  t["tags"] = ["fun", "programming", "learn"]
  t["collaborators"] = ["alice", "bob", "charlie"]
  t["created"] = Time.now
end

GQL

該当なし

このコードでは、プロパティ tags に対して 3 つの値、プロパティ collaborators に対して 3 つの値、さらに現在の日付に設定された created を持つ Task エンティティが作成されます。この場合、プロパティ値の組み合わせとして可能性のあるものそれぞれに対応するには、9 つのインデックス エントリが必要になります。

('fun', 'alice', NOW())
('fun', 'bob', NOW())
('fun', 'charlie', NOW())

('programming', 'alice', NOW())
('programming', 'bob', NOW())
('programming', 'charlie', NOW())

('learn', 'alice', NOW())
('learn', 'bob', NOW())
('learn', 'charlie', NOW())

同じプロパティが複数回繰り返し使われている場合、Cloud Datastore がインデックス爆発を検出し、代替のインデックスを推奨する場合があります。ただし、それ以外のすべての状況(この例で定義されているクエリなど)では、インデックス爆発が生成されることになります。この場合、インデックス設定ファイルのインデックスを手動で次のように設定することにより、インデックス爆発を回避できます。

indexes:
- kind: Task
  properties:
  - name: tags
  - name: created
- kind: Task
  properties:
  - name: collaborators
  - name: created

このようにすることで必要なエントリ数が (|tags| * |created| + |collaborators| * |created|) のみになり、9 エントリから 6 エントリに減少します。

('fun', NOW())
('programming', NOW())
('learn', NOW())

('alice', NOW())
('bob', NOW())
('charlie', NOW())

commit オペレーションによってインデックスのエントリ数またはサイズの制限が超過した場合、そのオペレーションは失敗します。どの制限を超過し、どのカスタム インデックスが原因となったのかは、エラーのテキスト("Too many indexed properties" または "Index entries too large" など)によって示されます。構築時にエンティティの制限を超える新しいインデックスを作成すると、そのインデックスに対するクエリが失敗し、インデックスが GCP Console に Error 状態で表示されます。このような Error 状態のインデックスに対処するには、次の手順に従います。

  1. 該当するインデックスをインデックス設定ファイル(index.yaml)から削除します。
  2. 使用されていないインデックスの削除の説明に沿って、gcloud コマンドライン ツールに vacuum_indexes オプションを指定してインデックスをバキュームします。
  3. 次のいずれかを実行します。
    • インデックスの定義および対応するクエリを再構成する
    • インデックス爆発の原因となっているエンティティを削除する
  4. インデックスを index.yaml に追加し直します。
  5. インデックスの更新の説明に沿って、update_indexes オプションを指定した gcloud コマンドライン ツールを使用してインデックスを更新します。

インデックス爆発は、リスト プロパティを使用するカスタム インデックスが必要なクエリを避けることで回避できます。すでに説明したように、このようなクエリとしては複数の並べ替え順序を持つクエリや、等式フィルタと不等式フィルタが混在するクエリなどが挙げられます。

射影のインデックス

射影クエリでは、射影で指定されているすべてのプロパティが Cloud Datastore のインデックスに含まれるようにする必要があります。Cloud Datastore エミュレータを使用すると、必要なインデックスがインデックス設定ファイル(index.yaml)内に自動生成されます。このファイルはアプリケーションと一緒にアップロードされます。

必要なインデックスの数を最小限に抑える方法の 1 つとして、必ずしもすべてが必要でない場合であっても、同じ複数のプロパティを一貫して射影するという方法が挙げられます。たとえば、次のクエリはそれぞれ個別のインデックスを必要とします。

SELECT priority, percent_complete FROM Task

SELECT priority, percent_complete, created FROM Task

ただし created が不要であっても、常に prioritypercent_completecreated の各プロパティを射影することで、必要なインデックスは 1 つだけになります。

既存のクエリを射影クエリに変換する際、射影されたプロパティがクエリの別の部分に含まれていない場合は、新しいインデックスを構築しなければならない場合があります。たとえば、次のような既存のクエリがあるとします。

SELECT * FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

必要なインデックスは次のとおりです。

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete

このクエリを次のいずれかの射影クエリに変換します。

SELECT created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

SELECT priority, percent_complete, created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

この場合、新しいプロパティ(created)を伴うため、新しいインデックスを構築する必要があります。

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete
  - name: created

ただし、次のクエリ

SELECT priority, percent_complete FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

では必要なインデックスは変わりません。これは射影される priority プロパティと percent_complete プロパティが既存のクエリにすでに含まれているためです。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Cloud Datastore ドキュメント