是否可以使用新的Firebase数据库Cloud Firestore来计算一个集合有多少项?

如果是,我该怎么做?


当前回答

最简单的方法是读取“querySnapshot”的大小。

db.collection("cities").get().then(function(querySnapshot) {      
    console.log(querySnapshot.size); 
});

你也可以在querySnapshot中读取文档数组的长度。

querySnapshot.docs.length;

或者如果“querySnapshot”为空,则读取空值,将返回一个布尔值。

querySnapshot.empty;

其他回答

使用admin. keystore . fieldvalue . Increment增加一个计数器:

exports.onInstanceCreate = functions.firestore.document('projects/{projectId}/instances/{instanceId}')
  .onCreate((snap, context) =>
    db.collection('projects').doc(context.params.projectId).update({
      instanceCount: admin.firestore.FieldValue.increment(1),
    })
  );

exports.onInstanceDelete = functions.firestore.document('projects/{projectId}/instances/{instanceId}')
  .onDelete((snap, context) =>
    db.collection('projects').doc(context.params.projectId).update({
      instanceCount: admin.firestore.FieldValue.increment(-1),
    })
  );

在本例中,每次将文档添加到instances子集合时,我们都会增加项目中的instanceCount字段。如果该字段还不存在,它将被创建并增加到1。

增量在内部是事务性的,但如果需要更频繁地递增,则应该使用分布式计数器。

通常最好实现onCreate和onDelete而不是onWrite,因为你将调用onWrite进行更新,这意味着你在不必要的函数调用上花费了更多的钱(如果你更新了你的集合中的文档)。

据我所知,目前还没有内置的解决方案,只能在节点sdk中实现。 如果你有

db.collection('someCollection')

你可以使用

.select([fields])

定义要选择的字段。如果执行空select(),则只会得到一个文档引用数组。

例子:

db.collection (someCollection) .select () . get () ( (snapshot) => console.log(snapshot.docs.length) );

此解决方案只是针对下载所有文档的最坏情况的优化,并且不能扩展到大型集合!

再看看这个: 如何获得在一个集合与云Firestore的文件的数量计数

var variable=0
variable=variable+querySnapshot.count

那么如果你要在String变量上使用它,那么

let stringVariable= String(variable)

自9.11.0版本以来,有一个新的内置函数getCountFromServer(),它在不实际下载文档的情况下获取结果集中的文档数量。

https://firebase.google.com/docs/reference/js/firestore_#getcountfromserver

在2020年,Firebase SDK中还没有这个功能,但Firebase扩展(Beta)中有,不过设置和使用起来相当复杂……

合理的方法

帮手……(创建/删除似乎是多余的,但比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;
}

出口消防钩


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());
});

在行动

将跟踪构建根集合和所有子集合。

在/counters/ root路径下

现在收集计数将自动更新,最终!如果需要计数,只需使用收集路径并在其前面加上计数器即可。

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

限制

由于此方法使用单个数据库和文档,因此每个计数器的Firestore约束为每秒更新1次。它最终将是一致的,但在添加/删除大量文档的情况下,计数器将落后于实际收集计数。