web-dev-qa-db-ja.com

Firestoreでは、すべてのキーのインデックスを作成せずに、マップ内のキーを含む複合クエリをどのように実行できますか?

Firestoreでは、すべてのキーのインデックスを作成せずに、マップ内のキーを含む複合クエリをどのように実行できますか?

たとえば、ブログ投稿を保持するコレクションを考えてみましょう。各ブログ投稿にはカテゴリがあります。

Post {
    title: ..
    ...
    categories: {
        cats: true
        puppies: true
    }   
}

特定のカテゴリの投稿をページ分割された方法でクエリするには、次のようにします。

let query = db.collection(`/posts`)
    .where(`categories.${categoryId}`, '==', true)
    .orderBy('createdAt')
    .startAfter(lastDate)
    .limit(5);

しかし、これには複合インデックス(categories.<categoryId>およびcreatedAt)をすべての単一カテゴリに割り当てます。これを回避する方法はありますか?

私の場合、カテゴリはユーザーが生成し、簡単に200(Firestoreの複合インデックスの制限)を超える可能性があるため、すべてのカテゴリの複合インデックスを作成することはできません。

17
RyanM

これは、各カテゴリの値を並べ替えたいものに設定することで実行できます。 Firestoreには、これをカバーする ガイド があります。

Post {
    title: ..
    ...
    categories: {
        cats: createdAt
        puppies: createdAt
    }   
}

let query = db.collection(`/posts`)
    .where(`categories.${categoryId}`, '>', 0)
    .orderBy(`categories.${categoryId}`)
    .startAfter(lastDate)
    .limit(5);
8
abraham

私の知る限り、Firestoreはこれらのインデックスを自動生成する必要があります。 配列、リスト、およびセットのドキュメントページ から:

各カテゴリがマップのキーであり、すべての値がtrueである次の代替データ構造を検討してください。

// Sample document in the 'posts' collection
{
    title: "My great post",
    categories: {
        "technology": true,
        "opinion": true,
        "cats": true
    }
}

1つのカテゴリ内のすべてのブログ投稿を簡単に照会できるようになりました。

// Find all documents in the 'posts' collection that are
// in the 'cats' category.
db.collection('posts')
    .where('categories.cats', '==', true)
    .get()
    .then(() => {
        // ...
    });
)

この手法は、Cloud Firestoreが、ネストされたマップのフィールドを含むすべてのドキュメントフィールドに組み込みインデックスを作成するという事実に依存しています。

Where条件の左側は可変かもしれませんが、これらのインデックスが自動生成されるという事実は変わりません(私の知る限り)。

6

現在、Firestoreではarray-contains演算子が許可されています。
特定の値を含むドキュメントをフィルタリングする場合は、これを試してください。

まず、マップフィールドを配列フィールドに変更します。

Post {
    title: ..
    ...
    categories: [
        cats,
        puppies
    ]
}

次に、異なるフィールドごとにarray-containsおよびorderByを使用します。

let query = db.collection(`/posts`)
    .where('categories', 'array-contains', 'cats')
    .orderBy('createdAt')
    .startAfter(lastDate)
    .limit(5);

array-contains演算子に関する公式ドキュメントは、 here から確認できます。

2
wonsuc

データストアを再構築してください。 Firebaseのドキュメント はここで非常に役立ちます。

クエリの制限

Cloud Firestoreは、次の種類のクエリをサポートしていません。

  • 前のセクションで説明したように、さまざまなフィールドで範囲フィルターを使用したクエリ。
  • 複数のコレクションまたはサブコレクションにわたる単一クエリ。各クエリは、ドキュメントの単一のコレクションに対して実行されます。データ構造がクエリに与える影響の詳細については、「 データ構造の選択 」を参照してください。
  • 個々のアレイメンバーのクエリ。ただし、 配列、リスト、およびセットの操作 の手法を使用して、配列のようなデータをモデル化およびクエリできます。
  • 論理ORクエリ。この場合、各OR条件ごとに個別のクエリを作成し、クエリ結果をアプリにマージする必要があります。
  • !=句を使用したクエリ。この場合、クエリを大なりクエリと小なりクエリに分割する必要があります。たとえば、クエリ句where( "age"、 "!="、 "30")はサポートされていませんが、2つのクエリを結合して同じ結果セットを取得できます。1つは句where( "age"、 "< "、" 30 ")およびwhere(" age "、"> "、30)句を持つもの。
2
Ron Royston