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

如果是,我该怎么做?


当前回答

使用带有偏移量和限制的分页的解决方案:

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条记录!

其他回答

根据本文档,Cloud Firestore支持count()聚合查询,并在预览版中可用。

颤振/飞镖代码丢失(在写这篇文章的时候),所以我玩了一下,下面的函数似乎可以工作:

  Future<int> getCount(String path) async {
    var collection = _fireStore.collection(path);
    var countQuery = collection.count();
    var snapShot = await countQuery.get(source: AggregateSource.server);
    return snapShot.count;
  }

使用带有偏移量和限制的分页的解决方案:

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条记录!

解决办法是:

在firebase文档中编写一个计数器,每次创建新条目时都在事务中增加计数器

您将计数存储在新条目的字段中(即:position: 4)。

然后在该字段上创建一个索引(position DESC)。

您可以对查询执行跳过+限制操作。Where("position", "<" x).OrderBy("position", DESC)

希望这能有所帮助!

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

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

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

db.collection('someCollection')

你可以使用

.select([fields])

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

例子:

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

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

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