Firestoreの基本リファレンス


まずはこれだけ覚えておけ的なやつ

基本

全部Promiseで返ってくる。

Get = get

db.collection("cities").doc("SF").get()
    .then( doc => doc.data() );

Create, Update = set

db.collection("cities").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000,
    regions: ["west_coast", "norcal"] });

Partial Update = update

db.collection("cities").doc("DC").update({
    capital: true
});

Delete = delete()

db.collection("cities").doc("DC").delete()

Query

db.collection("cities").where("capital", "==", true).get()
    .then( querySnapshot => {
        querySnapshot.forEach( doc => doc.data() );
    });
db.collection("cities").where("population", ">", 100000).orderBy("population","desc").limit(3);

Transaction

const sfDocRef = db.collection("cities").doc("SF");

return db.runTransaction( transaction => {
    // This code may get re-run multiple times if there are conflicts.
    return transaction.get(sfDocRef)
      .then( sfDoc => {
          if (!sfDoc.exists) {
              throw "Document does not exist!";
          }
          const newPopulation = sfDoc.data().population + 1;
          transaction.update(sfDocRef, { population: newPopulation });
      });
});

async/awaitでまとめて書いたほうが読みやすそう。

Streaming

onSnapshot を使う。

db.collection("cities").doc("SF")
    .onSnapshot(doc => doc.data() );

onSnapshotに渡しているのは、リスナーという扱いになる。
コンテンツが変更されるたびに、リスナーにデータが流れる。

Metadata

このとき、doc には doc.metadata のかたちでmetadataがついている。
metadataには、例えば metadata.hasPendingWrites プロパティなどがあり、ローカルでは変更されたがサーバ側では変更が終わってない、みたいな情報が付与されている。

また、リスナーで受け取るイベントの詳細レベルを制御することもできる。メタデータの変更があった場合のみListenする場合

db.collection("cities").doc("SF")
    .onSnapshot({
        // Listen for document metadata changes
        includeMetadataChanges: true
    }, function(doc) {
        // ...
    });

docChanges()

db.collection("cities").where("state", "==", "CA")
    .onSnapshot(doc => {
        doc.docChanges().forEach( change => {
            if (change.type === "added") {
                console.log("New city: ", change.doc.data());
            }
            if (change.type === "modified") {
                console.log("Modified city: ", change.doc.data());
            }
            if (change.type === "removed") {
                console.log("Removed city: ", change.doc.data());
            }
    });

コレクションへのクエリ結果の変更状況をリスニングする場合。
都市が追加されたら、added typeのchangeが発生する。

AngularFire

AngularFireでは、これらをObservableで取り扱えるように抽象化してある。
(詳しくは https://qiita.com/awa2/items/a7dbfa215365f46dd675)

  • valueChanges()
    • get()したデータをJSON配列でそのままObservableとして流す
  • snapshotChanges()
    • onSnapshot()を使って、メタデータを含む現在のデータを流す
    • Observable<DocumentChangeAction[]> が流れてくる
  • stateChanges()
    • onSnapshot()を使って、メタデータ含む直近の変更を流す
    • Observable<DocumentChangeAction[]> が流れてくる
interface DocumentChangeAction {
  type: DocumentChangeType; // 'added' | 'modified' | 'removed';
  payload: {
    type: DocumentChangeType;
    oldIndex: number;
    newIndex: number;
    doc: {
      exists: boolean;
      ref: DocumentReference;
      id: string;
      metadata: SnapshotMetadata;
      data(): DocumentData;
      get(fieldPath: string): any;
    }
  }
}