FirestoreのReferenceとSnapshotの大まかな理解(Tips)

2 min読了の目安(約2600字TECH技術記事

firestoreのオブジェクトってDocumentReferenceとかQuerySnapshotとか
色々あって紛らわしくて、特に初めての場合混乱しがちですよね。
自分も久々に触ったのですが「どういう関係だったっけ?」となってしまいました。

以前勉強したときに全体像を捉えられるようにしていたのですが、
それをアウトプットしていなかったので全体感を捉えるTipsとして載せておきます。

クエリ(query)

Firebaseに送るリクエストのこと

firebaseはそのqueryに対するデータがなくても、
必ずReference or Snapshotをレスポンスとして返す

ReferenceとSnapshot

Firebaseには大まかに2つのオブジェクト郡がある

1. Reference
2. Snapshot

Reference(概要)

オブジェクトが存在する「現在の場所」を示す
=> データは持たない

Snapshot(概要)

オブジェクト(のデータ)のこと

Reference(詳細)

大まかに以下の2つに分けられる

1. DocumentReference
2. CollectionReference

DocumentReference

firestore.doc('/users/:userId')などで参照可能

1. オブジェクトのReferenceを参照する
2. CRUD操作できる(referenceのsnapshotがオブジェクトのため)
   代表的なメソッド:set, get, update, delete
3. getするとDocumentSnapshotが返される

CollectionReference

firestore.collection('/users')などで参照可能

1. 配列のReferenceを参照する
2. CRUD操作できない(referenceのsnapshotが配列のため)
   代表的なメソッド:add, get
3. getするとQuerySnapshotが返される
   (**※CollectionSnapshotではない**)

Snapshot(詳細)

1. 「場所」ではなく、実際のデータのこと(オブジェクトとは言ってない)
2. どのReferenceから参照するかによってオブジェクトの型が変わる
3. snapshot.refのように、SnapshotからReferenceを参照できる

Snapshotは大まかに3つ種類がある

1. DocumentSnapshot
2. QuerySnapshot
3. QueryDocumentSnapshot

ReferenceとSnapshotの対応関係は以下のようになる

DocumentReferenceから参照可能
  1. DocumentSnapshot

CollectionReferenceから参照可能
  2. QuerySnapshot
  3. QueryDocumentSnapshot

QuerySnapshotとQueryDocumentSnapshotの違い

上記2つは何が違うのか?

 1. QuerySnapshot
    CollectionReferenceから取得した配列の型
 2. QueryDocumentSnapshot
    QuerySnapshot(配列)内部のそれぞれのオブジェクトの型
const collectionRef = firestore.collection('cities')
const querySnapshot = collectionRef.get()
const array = querySnapshot.docs.map(snapshot => (
  // ここで参照できるsnapshotがqueryDocumentSnapshot
))

まとめると

 1. DocumentSnapshot
    DocumentReferenceから取得したオブジェクトの型
 2. QuerySnapshot
    CollectionReferenceから取得した配列の型
 3. QueryDocumentSnapshot
    QuerySnapshot内部のそれぞれのオブジェクトの型

包含関係は

DocumentReference
  DocumentSnapshot

CollectionReference
  QuerySnapshot
    QueryDocumentSnapshot

DocumentSnapshot

1. existsでオブジェクトの存在確認ができる
2. data()でJSON(オブジェクト)を取得できる

querySnapshot

1. emptyで内部データの存在確認ができる
2. docs()でqueryDocumentSnapshotを含む配列を取得できる

queryDocumentSnapshot

DocumentSnapshotとほぼ同じ

まとめ

Referenceがつくものは「現在の場所」  
Documentがつくものは「実際のデータ」  

と考えると理解しやすいと思います。

そうするとReferenceにはCRUD操作が使える、というのもうなずけます
(「〜に配置する、〜から削除する」の「〜」は場所=Referenceですよね)

加えて、上記のように考えることができると
referenceは「場所」だから「〜に配置する」と考えてset使えるよな
と連想できるので、簡単なメソッドについてはいちいちドキュメントを
参照しなくて済みそうです(読まなくていいとはいってない)