😺

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

2021/01/15に公開

概要

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

collection/
├── document1
│   └── subcollection
│       ├── documentA
│       │   └── sortNum: 4 (数字)
│       └── documentB
│           └── sortNum: 2 (数字)
└── document2
    └── subcollection
        ├── documentC
        │   └── sortNum: 1 (数字)
        └── documentD
            └── sortNum: 3 (数字)
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. 除外を追加 へ

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

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

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

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

documentA
documentD
documentB

Discussion