GAミント至上主義

安くて速いが好きなWEBアプリ開発者。最近はPython, Vue.js, Firebase, GKE。@株式会社ビズオーシャン

Firestoreでコレクションだけ持ってるドキュメントを一覧で取得できなくてハマったらFirestoreの構造を実感できた

Firebase Admin SDKでデータを抜き出そうとしたら取れなくてハマった。
結論としてはコレクションのみを持つドキュメントは一覧を取得することができないのが分かった。

Firebase Consoleだと見れるけどどうやってるかわからないが、よく見ると注意書きがあることに後で気づく。

f:id:uyamazak:20180808111905p:plain

全体のデータ構造は下記のようになっている

/userdata/{uId}/backups/{backupId}

あえて図にすると下記のような感じ。

  • がコレクション、#がドキュメント
-userdata
  #yamada
    -backups
      #backup1(データ入り)
      #backup2
      #backup3
  #suzuki
    -backups
      #backup1
      #backup2
      #backup3
var cRef = db.collection('userdata')
cRef.get()
    .then(snap =>{
      console.log(snap.size)
    })
# 0

これはyamadaとsuzukiが欲しいがとれない

しかしbackupsまで入れば取れる

cRef.doc('yamada')
    .collection('backups')
    .get()
    .then(snap =>{
      console.log(snap.size)
    })
# 3

最初ルートは取れないかと思ったけど関係はなく、いろいろ試した末の違いとしては、ドキュメントにデータがあるかどうか。
userdata/yamadaのドキュメントにすでにあるbackupsのほかにフィールドを追加すれば取得することができた。

Firestoreのドキュメントはコレクションとフィールド(Key, Valueのデータ)の両方を持つことができる、ファイルシステムで言うディレクトリみたいなものなのでややこしい。

Firestoreを大きなJSONと考えるとこの問題は理解できないけど、Firestoreはファイルシステムや、JSON専用のKVSのようなものだと考え、途中のパスは単なるパスであり、jsの配列ような実体はないと考えると納得がいった。

そう体感してから下記ドキュメントを読むとそれはそうだなと思えた。
Cloud Firestore データモデル  |  Firebase

コレクションを「作成」したり「削除」したりする必要はありません。コレクション内の最初のドキュメントを作成すると、コレクションはすでに存在しています。コレクション内のすべてのドキュメントを削除すると、コレクションは存在しなくなります。
警告: ドキュメントを削除しても、そのサブコレクションは削除されません。

サブコレクションが関連付けられているドキュメントを削除しても、そのサブコレクションは削除されません。その後もサブコレクションには、リファレンスによるアクセスが可能です。たとえば、db.collection('coll').doc('doc') によって参照されるドキュメントは存在しなくなったにもかかわらず、db.collection('coll').doc('doc').collection('subcoll').doc('subdoc') によって参照されるドキュメントは存在する場合があります。ドキュメントを削除するときにサブコレクション内のドキュメントも削除する場合は、コレクションを削除するで説明されているように、手動で削除する必要があります。