如何在 Cloud Firestore 文档中列出子集合

How to list subcollections in a Cloud Firestore document

提问人:skylize 提问时间:10/6/2017 最后编辑:Frank van Puffelenskylize 更新时间:6/22/2023 访问量:14898

问:

假设我在 Cloud Firestore 中存储了这个最小的数据库。如何检索 和 的名称?subCollection1subCollection2

rootCollection {
    aDocument: {
        someField: { value: 1 },
        anotherField: { value: 2 }
        subCollection1: ...,
        subCollection2: ...,
    }
}

我希望能够只读取 的 ids,但当我阅读文档时,只会显示字段。aDocumentget()

rootRef.doc('aDocument').get()
  .then(doc =>

    // only logs [ "someField", "anotherField" ], no collections
    console.log( Object.keys(doc.data()) )
  )
JavaScript Firebase 谷歌云 Firestore

评论

0赞 Victor Nascimento 10/6/2017
难道程序员不应该事先知道集合吗?您的用例是什么?
1赞 skylize 10/6/2017
@VictorNascimento。该用例正在处理缺乏递归删除的问题。我正在尝试删除包含子集合的文档,这些子集合也应该删除,因为它们是文档的子项并且不再有效。是的,目前我碰巧知道集合的名称,但是需要手动枚举可能无限深度的树上的每个子集合只是为了删除单个文档,这将是一种可怕的做法。
0赞 TheAddonDepot 10/6/2017
子集合不是用于引用子集合的父文档的成员/属性。
0赞 Kato 3/13/2019
递归删除可以在 Admin SDK 中和通过 CLI 完成。请参阅此处的文档。
0赞 Heshan Sandeepa 7/10/2023
点击这里查看 stackoverflow.com/a/76654434/2126077

答:

6赞 Dan McGrath 10/6/2017 #1

目前不支持在客户端 SDK(Web、iOS、Android)中从 Firestore 获取(子)集合列表。从文档中:

无法使用移动/Web 客户端库检索集合列表。在受信任的服务器环境中,您只应在管理任务中查找集合名称。如果您发现在移动/Web 客户端库中需要此功能,请考虑重构数据,以便子集合名称是可预测的。

服务器端 SDK 中,此功能确实存在。例如,在 Node.js 中,您将遵循以下方法:ListCollectionIds

var firestore = require('firestore.v1beta1');

var client = firestore.v1beta1({
  // optional auth parameters.
});

// Iterate over all elements.
var formattedParent = client.anyPathPath("[PROJECT]", "[DATABASE]", "[DOCUMENT]", "[ANY_PATH]");

client.listCollectionIds({parent: formattedParent}).then(function(responses) {
    var resources = responses[0];
    for (var i = 0; i < resources.length; ++i) {
        // doThingsWith(resources[i])
    }
})
.catch(function(err) {
    console.error(err);
});

评论

0赞 skylize 10/6/2017
不完全是好消息,但至少它即将到来。感谢您的更新。对当前可用的递归删除具有子集合的文档的技术有任何建议吗?
0赞 TheAddonDepot 10/6/2017
@Dan McGrath:firestore 只是云数据存储的更名吗?
0赞 Dan McGrath 10/6/2017
@skylize -> 触发云函数执行。
0赞 Dan McGrath 10/6/2017
@DimuDesigns -> No.
0赞 skylize 10/6/2017
@Dan McGrath:触发云函数有何帮助?你是说现在在 Cloud Functions 中可用吗?ListCollectionIds
0赞 Ronnie Royston 12/1/2017 #2

文档中不是很详细吗?

/**
 * Delete a collection, in batches of batchSize. Note that this does
 * not recursively delete subcollections of documents in the collection
 */
function deleteCollection(db, collectionRef, batchSize) {
    var query = collectionRef.orderBy('__name__').limit(batchSize);

    return new Promise(function(resolve, reject) {
        deleteQueryBatch(db, query, batchSize, resolve, reject);
    });
}

function deleteQueryBatch(db, query, batchSize, resolve, reject) {
    query.get()
        .then((snapshot) => {
            // When there are no documents left, we are done
            if (snapshot.size == 0) {
                return 0;
            }

            // Delete documents in a batch
            var batch = db.batch();
            snapshot.docs.forEach(function(doc) {
                batch.delete(doc.ref);
            });

            return batch.commit().then(function() {
                return snapshot.size;
            });
        }).then(function(numDeleted) {
            if (numDeleted <= batchSize) {
                resolve();
                return;
            }

            // Recurse on the next process tick, to avoid
            // exploding the stack.
            process.nextTick(function() {
                deleteQueryBatch(db, query, batchSize, resolve, reject);
            });
        })
        .catch(reject);
}

评论

0赞 skylize 12/5/2017
在您在此处发布的所有代码中,与我的问题相关的唯一部分是顶部的注释,“这不会递归删除集合中文档的子集合”。我的具体预期用例是手动递归子集合,以便我可以按照文档中的说明删除它们。然而,由于某种疯狂的原因,我无法获得子集合列表来知道要删除什么。
0赞 Bruno Braga 12/8/2017
你想出什么了吗?
0赞 Ronnie Royston 12/8/2017
doc.data().someField.subCollection1或 或 ?doc.data().someField.subCollection1.val()doc.data().someField.subCollection1.val
5赞 0xC0DEBA5E 1/16/2018 #3

似乎他们添加了一个名为 Node.js 的方法:getCollections()

firestore.doc(`/myCollection/myDocument`).getCollections().then(collections => {
  for (let collection of collections) {
    console.log(`Found collection with id: ${collection.id}`);
  }
});

本示例打印出文档的所有子集合/myCollection/myDocument

评论

1赞 skylize 2/6/2018
这看起来很有希望。由于这个问题,我不得不放弃使用 Firestore,并且没有机会再试一次。我希望我的问题能为其他人带来更好的体验。如果按照您的建议解决了这个问题,那么我希望我有机会再试一次。
2赞 danday74 8/19/2022 #4

这个答案在文档

可悲的是,文档不清楚您导入的内容。

根据文档,我的代码最终看起来像这样:

import admin, { firestore } from 'firebase-admin'

let collections: string[] = null
const adminRef: firestore.DocumentReference<any> = admin.firestore().doc(path)
const collectionRefs: firestore.CollectionReference[] = await adminRef.listCollections()
collections = collectionRefs.map((collectionRef: firestore.CollectionReference) => collectionRef.id)

这当然是 Node.js 服务器端代码。根据文档,这不能在客户端上完成。