Cloud Firestore collection count

后端 未结 17 1546
庸人自扰
庸人自扰 2020-11-22 09:25

Is it possible to count how many items a collection has using the new Firebase database, Cloud Firestore?

If so, how do I do that?

17条回答
  •  故里飘歌
    2020-11-22 09:54

    In 2020 this is still not available in the Firebase SDK however it is available in Firebase Extensions (Beta) however it's pretty complex to setup and use...

    A reasonable approach

    Helpers... (create/delete seems redundant but is cheaper than onUpdate)

    export const onCreateCounter = () => async (
      change,
      context
    ) => {
      const collectionPath = change.ref.parent.path;
      const statsDoc = db.doc("counters/" + collectionPath);
      const countDoc = {};
      countDoc["count"] = admin.firestore.FieldValue.increment(1);
      await statsDoc.set(countDoc, { merge: true });
    };
    
    export const onDeleteCounter = () => async (
      change,
      context
    ) => {
      const collectionPath = change.ref.parent.path;
      const statsDoc = db.doc("counters/" + collectionPath);
      const countDoc = {};
      countDoc["count"] = admin.firestore.FieldValue.increment(-1);
      await statsDoc.set(countDoc, { merge: true });
    };
    
    export interface CounterPath {
      watch: string;
      name: string;
    }
    
    

    Exported Firestore hooks

    
    export const Counters: CounterPath[] = [
      {
        name: "count_buildings",
        watch: "buildings/{id2}"
      },
      {
        name: "count_buildings_subcollections",
        watch: "buildings/{id2}/{id3}/{id4}"
      }
    ];
    
    
    Counters.forEach(item => {
      exports[item.name + '_create'] = functions.firestore
        .document(item.watch)
        .onCreate(onCreateCounter());
    
      exports[item.name + '_delete'] = functions.firestore
        .document(item.watch)
        .onDelete(onDeleteCounter());
    });
    
    

    In action

    The building root collection and all sub collections will be tracked.

    Here under the /counters/ root path

    Now collection counts will update automatically and eventually! If you need a count, just use the collection path and prefix it with counters.

    const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
    const collectionCount = await db
      .doc('counters/' + collectionPath)
      .get()
      .then(snap => snap.get('count'));
    

    Limitations

    As this approach uses a single database and document, it is limited to the Firestore constraint of 1 Update per Second for each counter. It will be eventually consistent, but in cases where large amounts of documents are added/removed the counter will lag behind the actual collection count.

提交回复
热议问题