見出し画像

複数ドキュメント(document)以下のサブコレクション(subcollection)を一度に取得して orderBy をかけたい

概要

Cloud Firestore の、複数ドキュメント(document)にぶら下がる サブコレクション(subcollection)以下を一度に取得して、sortNumの値で orderBy をかけたい。

collection/
├── document1
│   └── subcollection
│       ├── documentA
│       │   └── sortNum: 4 (数字)
│       └── documentB
│           └── sortNum: 2 (数字)
└── document2
   └── subcollection
       ├── documentC
       │   └── sortNum: 1 (数字)
       └── documentD
           └── sortNum: 3 (数字)

- こんなことはできない例
https://firebase.google.com/docs/reference/js/firebase.firestore.CollectionReference#doc
を 読む限り、doc メソッド には ワイルドカード機能はないので、以下のようなことはできません。

const db = firebase.firestore()
const ref = db.collection('collection')

ref
 .doc('*') // こんなことはできない
 .collection('subcollection')
 .orderBy('sortNum', 'desc')
 .limit(3)
 .get()
 .then((snapshot) => {
 ...

方法

collectionGroup を使えば、同名の Collection以下 を一度に取得することができます。

const db = firebase.firestore()

db.collectionGroup('subcollection')
 .orderBy('sortNum', 'desc')
 .limit(3)
 .then((snapshot) => {
 ...

しかしこれだけでは、orderByを使おうとすると 以下エラーが出力されます。

FirebaseError: The query requires a COLLECTION_GROUP_DESC index for collection content and field sortNum. You can create it here: https://console.firebase.google.com/...

要するに、Collection group スコープ は 自動的に index が作られないからです。
Firebase コンソール の インデックス画面を見ると以下のようになっています。

画像1

1. 除外を追加 へ

画像2

2. indexを設定したい コレクション ID と フィールドのパス を入力
コレクション グループ の チェックボックス をオン

画像3

3. 必要なものを選んで有効にします

画像4

4. しばらくすると index設定が完了します。
「除外」という名前はややこしいですが、要するに 自動インデックス設定 に上書きをする感じです。
コレクション の チェックボックスは オン にしていないので、Collection scopeの設定上書きはされないわけです。

画像5

orderBy が desc で、limit を 3 にしているので
これで 以下の順にデータが並んだ状態で 計3つを取得できます。

documentA
documentD
documentB

この記事が気に入ったらサポートをしてみませんか?