You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase Firestore查询指定子集合文档返回数量为0的问题求助

解决Firestore查询子集合父文档数量为0的问题

你遇到的问题其实是Firestore一个容易踩的特性坑:当你只在某个文档下创建子集合,但没有给这个文档本身设置任何字段时,这个文档不会出现在集合的get()查询结果里。

问题根源

看你的addFolder代码,你直接在Starred Messages集合下的folderName文档里创建了子集合KEY_STARRED_MESSAGE_FOLDERS,但这个folderName文档本身没有任何数据(没有设置任何键值对)。Firestore的集合查询(get()方法)只会返回那些包含至少一个字段的文档,空文档(只有子集合没有自身数据)会被自动忽略,所以你的Toast才会显示文档数量为0。

解决方案

这里有两种可行的解决方法,你可以根据需求选择:

方法1:创建文件夹时给父文档添加至少一个字段

这是更推荐的方案,因为给文件夹文档添加元数据(比如创建时间)对后续功能扩展很有用。修改你的addFolder方法,先给folderName文档设置数据,再创建子集合:

private void addFolder(String folderName){
    // 给文件夹文档本身添加元数据(比如服务器时间戳)
    HashMap<String, Object> folderMetadata = new HashMap<>();
    folderMetadata.put("createdAt", FieldValue.serverTimestamp());

    FirebaseFirestore db = FirebaseFirestore.getInstance();
    String userId = preferenceManager.getString(Constants.KEY_USER_ID);

    // 先创建/更新文件夹文档
    db.collection(Constants.KEY_COLLECTION_USERS)
            .document(userId)
            .collection(Constants.KEY_COLLECTION_STARRED_MESSAGE)
            .document(folderName)
            .set(folderMetadata)
            .addOnSuccessListener(aVoid -> {
                // 文件夹文档创建成功后,再添加子集合的示例数据
                HashMap<String, String> map = new HashMap<>();
                map.put("sampleValue","sampleValue");
                db.collection(Constants.KEY_COLLECTION_USERS)
                        .document(userId)
                        .collection(Constants.KEY_COLLECTION_STARRED_MESSAGE)
                        .document(folderName)
                        .collection(Constants.KEY_STARRED_MESSAGE_FOLDERS)
                        .document("sampleValueFolder2358")
                        .set(map)
                        .addOnCompleteListener(task -> {
                            if (task.isSuccessful())
                                Log.d("folderCreation","done");
                            else
                                Log.d("folderCreation","fail");
                        });
            })
            .addOnFailureListener(e -> Log.d("folderCreation", "Failed to create folder: " + e.getMessage()));
}

修改后,你的getFolders方法不需要改动,get()查询就能正常获取到文件夹文档了。

方法2:使用listDocuments()获取所有文档(包括空文档)

如果你不想给文件夹文档添加字段,可以用listDocuments()方法替代get(),这个方法会列出集合下所有的文档引用,不管文档有没有数据:

private void getFolders(){
    FirebaseFirestore.getInstance().collection(Constants.KEY_COLLECTION_USERS)
            .document(preferenceManager.getString(Constants.KEY_USER_ID))
            .collection(Constants.KEY_COLLECTION_STARRED_MESSAGE)
            .listDocuments()
            .addOnCompleteListener(task -> {
                if (task.isSuccessful()) {
                    List<DocumentReference> folderDocRefs = task.getResult();
                    Toast.makeText(this, "" + folderDocRefs.size(), Toast.LENGTH_SHORT).show();
                    folders.clear();
                    for (DocumentReference docRef : folderDocRefs) {
                        Folder folder = new Folder();
                        folder.name = docRef.getId();
                        folders.add(folder);
                    }
                    adapter.notifyDataSetChanged();
                    binding.refreshLayout.setRefreshing(false);
                } else {
                    Log.e("getFolders", "Failed to load folders", task.getException());
                    binding.refreshLayout.setRefreshing(false);
                }
            });
}

注意:listDocuments()是客户端API,无法通过Firestore安全规则进行过滤,不过你的场景是获取当前用户自己的文件夹,所以这个限制影响不大。

总结

优先选择方法1,因为额外的元数据能让你后续更容易扩展功能(比如按创建时间排序文件夹)。如果只是临时需求,方法2可以快速解决问题。

内容的提问来源于stack exchange,提问作者Sambhav Khandelwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 08:37:51