我想计算具有Firestore云功能的子集合中的文档数。
我的数据库如下所示:groups / {groupId} / members / {memberId}
我想计算每个组的成员数(memberId)。这意味着每个组可以具有不同数量的成员,并且可以增加或减少灵活性。
会对您的想法感到高兴:-)。
答案 0 :(得分:0)
我考虑了两种可能的方法。
1。直接计算馆藏文件
您将像使用size
的QuerySnapshot
属性
admin.firestore().collection('groups/{groupId}/members/{memberId}')
.get()
.then(querySnapshot => {
console.log(querySnapshot.size);
//....
return null;
});
这里的主要问题是成本 ,如果子集合包含很多文档:通过执行此查询,您需要为每个文档支付一读费用子集合的内容。
2。另一种方法是为每个子集合维护一些计数器
您将编写两个Cloud Function, 基于分布式计数器 ,如Firebase文档项目https://firebase.google.com/docs/firestore/solutions/counters中所述。在下面的示例中,我们使用3个分片。
首先,当将新文档添加到subCollec
子集合中时,Cloud Function将增加计数器:
//....
const num_shards = 3;
//....
exports.incrementSubCollecCounter = functions
.firestore.document('groups/{groupId}/members/{memberId}')
.onCreate((snap, context) => {
const groupId = context.params.groupId;
const shard_id = Math.floor(Math.random() * num_shards).toString();
const shard_ref = admin
.firestore()
.collection('shards' + groupId)
.doc(shard_id);
if (!snap.data().counterIncremented) {
return admin.firestore().runTransaction(t => {
return t
.get(shard_ref)
.then(doc => {
if (!doc.exists) {
throw new Error(
'Shard doc #' +
shard_id +
' does not exist.'
);
} else {
const new_count = doc.data().count + 1;
return t.update(shard_ref, { count: new_count });
}
})
.then(() => {
return t.update(snap.ref, {
counterIncremented: true //This is important to have the Function idempotent, see https://cloud.google.com/functions/docs/bestpractices/tips#write_idempotent_functions
});
});
});
} else {
console.log('counterIncremented NOT NULL');
return null;
}
});
然后,当从subCollec
子集合中删除文档时,第二个Cloud Function将减少计数器:
exports.decrementSubCollecCounter = functions
.firestore.document('groups/{groupId}/members/{memberId}')
.onDelete((snap, context) => {
const groupId = context.params.groupId;
const shard_id = Math.floor(Math.random() * num_shards).toString();
const shard_ref = admin
.firestore()
.collection('shards' + groupId)
.doc(shard_id);
return admin.firestore().runTransaction(t => {
return t.get(shard_ref).then(doc => {
if (!doc.exists) {
throw new Error(
'Shard doc #' +
shard_id +
' does not exist.'
);
} else {
const new_count = doc.data().count - 1;
return t.update(shard_ref, { count: new_count });
}
});
});
});
在这里,与解决方案1进行比较,因为我们有3个分片,所以当您想了解subCollec
子集合中的文档数时,您只需读取3个文档。
有关如何初始化分布式计数器的详细信息,请参阅文档。您必须为每个groupId集合(即admin.firestore().collection('shards' + groupId)
)初始化一次
答案 1 :(得分:0)
花点时间让我开始工作,所以我想把它分享给其他人使用:
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.countDocumentsChange = functions.firestore.document('library/{categoryId}/documents/{documentId}').onWrite((change, context) => {
const categoryId = context.params.categoryId;
const categoryRef = db.collection('library').doc(categoryId)
let FieldValue = require('firebase-admin').firestore.FieldValue;
if (!change.before.exists) {
// new document created : add one to count
categoryRef.update({numberOfDocs: FieldValue.increment(1)});
console.log("%s numberOfDocs incremented by 1", categoryId);
} else if (change.before.exists && change.after.exists) {
// updating existing document : Do nothing
} else if (!change.after.exists) {
// deleting document : subtract one from count
categoryRef.update({numberOfDocs: FieldValue.increment(-1)});
console.log("%s numberOfDocs decremented by 1", categoryId);
}
return 0;
});