FirebaseをJavaScriptで触ってみているが、DBであるFirestoreからデータを取得する段階で何のメソッドを使えば何が返るのかよくわからず苦労している。そこで、基本的なクラスやメソッドに絞って互いの関係を図にしてみた。
図にしてみたら大して複雑ではなかったが、メソッドなのかプロパティなのかといった微妙な違いはまだ間違えそうなので、清書して残しておく。
なお、私はFirebaseを触るには以下の通り非常にスキルが低い。
- 生のJavaScriptは多少扱えるが、フレームワークやトランスパイラなどは全くわからない
- 非同期処理を扱ったことが無く、
Promise
は今回初めて知った - さらにNoSQLも初めてで、どのようなデータ構造が良いか模索中
- ドキュメント内にコレクションを持たせたり、フィールドのデータ型にreferenceを使ったり
図
文字数を減らすため記号による表現を多くしている。次節の「見方」を参照。
見方
- 角丸四角形はクラスを表す
- 入れ子になっているものは、内側が基本クラスで外側が派生クラス
- 派生クラスから基本クラスのプロパティやメソッドを呼べる
- オーバーライドは図にしていない
- 入れ子になっているものは、内側が基本クラスで外側が派生クラス
- 矢印はプロパティやメソッドを表す
- 矢尻付近の文字列はその名前と付加情報
-
()
無しはプロパティ、ありはメソッド -
{}
ありは戻り値の型がPromise<T>
-
[]
ありは戻り値の型がT[]
-
[field]
はフィールドの値の参照(そのうちのreferenceデータ型のみを図示)
-
- 戻り値が
null
やundefined
である可能性は省略 - 白い矢印は単に逆方向の参照が可能というだけ
- 矢尻付近の文字列はその名前と付加情報
- 上下、左右は繋がっている
- 左右方向は、ドキュメント内にコレクションを持てるということ
- 上下方向は、フィールドのデータ型にreferenceが使えるということ
補足説明
図で省略したことや読み取りにくいことについて補足する。具体的な説明用のコードは、公式ドキュメントのサンプルを基にした。
Firestore
からのreference取得
煩雑になるので図では省略したが、実際にコードを書くときは Firestore
のインスタンスが起点となる。ここからコレクションやドキュメントを取得して初めて図示した関係を使えるようになる。
Firestore
はメソッドとして collection()
と doc()
の両方を持つので、コレクションとドキュメントのどちらのreferenceも取得できる1,2。
// firebase初期化後、Firestoreのインスタンスを取得する
firebase.initializeApp(params);
const db = firebase.firestore();
// citiesコレクションのreferenceを取得する
let citiesRef = db.collection("cities");
クエリの設定と実行
Query
のところに where()
のループが描いてある。これは、クエリ用メソッドを繋げられることを示している。クエリを設定し終わったら(0個も可)、 get()
を呼び出すことでクエリの結果である QuerySnapshot
を得られる。
db.collection("cities")
.where("state", "==", "CA")
.where("population", ">", 1000000)
.get().then((querySnapshot) => {...});
クエリは where()
以外にも orderBy()
, limit()
, startAt()
などがある。 → クエリカーソルを使用したデータのページ設定
DocumentSnapshot
の取得
ドキュメントのデータを得るには DocumentSnapshot
を得る必要がある。図の矢印が示すように2通りの方法がある。
ひとつは DocumentReference
から直接 get()
する方法。ドキュメントが実際には存在しなくても取得されるが、その場合は data()
が undefined
を返す。( data()
を呼ばなくても exists
で存在確認できる)
もうひとつは QuerySnapshot
の docs
を参照する方法3。クエリに該当したドキュメント全てが得られるため配列となっている。また、派生クラスが得られるが、これは data()
が undefined
を返さないことが保証されている点のみ異なる。
// 単一のドキュメントの内容を取得する
db.collection("cities").doc("SF").get().then((doc) => {
if (doc.exists) {
console.log("Document data: ", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
});
// コレクション内のすべてのドキュメントを取得する
db.collection("cities").get().then((querySnapshot) => {
querySnapshot.docs.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
});
フィールドの値の取得
data()
が返す DocumentData
は、全てのフィールドをキーに持つ普通のオブジェクト。
特定のフィールドの値のみ欲しい場合は、 DocumentSnapshot
の get()
を使うことで DocumentData
の取得をスキップできる。
データ型には様々なものがサポートされている。そのうちreferenceは図に描いた通り DocumentReference
を指す。
参考
Firebase公式ドキュメントより
- APIリファレンス: firestore | JavaScript SDK | Firebase
- ドキュメント ガイド: Cloud Firestore | Firebase