是否可以使用新的Firebase数据库Cloud Firestore来计算一个集合有多少项?
如果是,我该怎么做?
是否可以使用新的Firebase数据库Cloud Firestore来计算一个集合有多少项?
如果是,我该怎么做?
当前回答
自9.11.0版本以来,有一个新的内置函数getCountFromServer(),它在不实际下载文档的情况下获取结果集中的文档数量。
https://firebase.google.com/docs/reference/js/firestore_#getcountfromserver
其他回答
不,目前还没有内置的聚合查询支持。然而,有几件事你可以做。
这里记录了第一个。您可以使用事务或云函数来维护聚合信息:
这个例子展示了如何使用一个函数来跟踪子集合中的评级数量,以及平均评级。
exports.aggregateRatings = firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite(event => {
// Get value of the newly added rating
var ratingVal = event.data.get('rating');
// Get a reference to the restaurant
var restRef = db.collection('restaurants').document(event.params.restId);
// Update aggregations in a transaction
return db.transaction(transaction => {
return transaction.get(restRef).then(restDoc => {
// Compute new number of ratings
var newNumRatings = restDoc.data('numRatings') + 1;
// Compute new average rating
var oldRatingTotal = restDoc.data('avgRating') * restDoc.data('numRatings');
var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings;
// Update restaurant info
return transaction.update(restRef, {
avgRating: newAvgRating,
numRatings: newNumRatings
});
});
});
});
jbb提到的解决方案在您只想不频繁地计数文档时也很有用。确保使用select()语句来避免下载所有文档(当您只需要一个计数时,这是很大的带宽)。select()目前仅在服务器sdk中可用,因此该解决方案不适用于移动应用程序。
自9.11.0版本以来,有一个新的内置函数getCountFromServer(),它在不实际下载文档的情况下获取结果集中的文档数量。
https://firebase.google.com/docs/reference/js/firestore_#getcountfromserver
使用带有偏移量和限制的分页的解决方案:
public int collectionCount(String collection) {
Integer page = 0;
List<QueryDocumentSnapshot> snaps = new ArrayList<>();
findDocsByPage(collection, page, snaps);
return snaps.size();
}
public void findDocsByPage(String collection, Integer page,
List<QueryDocumentSnapshot> snaps) {
try {
Integer limit = 26000;
FieldPath[] selectedFields = new FieldPath[] { FieldPath.of("id") };
List<QueryDocumentSnapshot> snapshotPage;
snapshotPage = fireStore()
.collection(collection)
.select(selectedFields)
.offset(page * limit)
.limit(limit)
.get().get().getDocuments();
if (snapshotPage.size() > 0) {
snaps.addAll(snapshotPage);
page++;
findDocsByPage(collection, page, snaps);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
findDocsPage是一个递归方法,用于查找集合的所有页面 selectedFields用于优化查询,只获得id字段而不是整个文档 限制每个查询页面的最大大小 页面定义用于分页的初始页面
从我做的测试来看,它可以很好地收集大约120k条记录!
我同意@Matthew的观点,如果你执行这样的查询,成本会很高。
[开发者开始项目前的建议]
由于我们在一开始就预见到了这种情况,因此实际上可以用一个文档创建一个集合,即计数器,将所有计数器存储在一个类型为number的字段中。
例如:
对于集合上的每个CRUD操作,更新计数器文档:
当你创建一个新的集合/子集合时:(在计数器中+1)[1写操作] 当你删除一个集合/子集合时:(-1在计数器中)[1写操作] 当你更新一个现有的集合/子集合时,在counter文档上什么都不做:(0) 当你读取一个现有的集合/子集合时,在计数器文档上什么都不做:(0)
下一次,当您想要获得集合的数量时,您只需要查询/指向文档字段。[1读操作]
此外,你可以将集合的名称存储在一个数组中,但这将是棘手的,数组在firebase中的条件如下所示:
// we send this
['a', 'b', 'c', 'd', 'e']
// Firebase stores this
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
// since the keys are numeric and sequential,
// if we query the data, we get this
['a', 'b', 'c', 'd', 'e']
// however, if we then delete a, b, and d,
// they are no longer mostly sequential, so
// we do not get back an array
{2: 'c', 4: 'e'}
所以,如果你不打算删除集合,你实际上可以使用数组来存储集合名称的列表而不是每次都查询所有的集合。
希望能有所帮助!
var variable=0
variable=variable+querySnapshot.count
那么如果你要在String变量上使用它,那么
let stringVariable= String(variable)