【问题标题】:How to retrieve documents of a sub collection in Firestore?如何在 Firestore 中检索子集合的文档?
【发布时间】:2018-03-18 17:20:46
【问题描述】:

我有一个结构如下图所示的数据库:

这里,我需要有多个品牌,每个品牌下还有多个子品牌。我之前尝试过使用“地图”,但它真的很乱,而且还了解到最好有多个文档。我对此很陌生,现在已经为此苦苦挣扎了 3-4 天。任何帮助将不胜感激。

  firebaseFirestore.collection("Coffee").addSnapshotListener(new EventListener<QuerySnapshot>() {
        @Override
        public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
            if (e != null) {
                Log.d(TAB, "Error : " + e.getMessage());
            }
            for (DocumentChange doc : documentSnapshots.getDocumentChanges()) {
                if (doc.getType() == DocumentChange.Type.ADDED) {
                    Log.d("Brand Name: ",doc.getDocument().getId());

                  //  how to retrieve documents of subCollection here? something like doc.getDocument().collection??

                }

            }

        }
    });

谢谢。

【问题讨论】:

    标签: android firebase google-cloud-firestore


    【解决方案1】:

    这真的很简单,试试这个。

     firebaseFirestore.collection("Coffee").addSnapshotListener(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
                if (e != null) {
                    Log.d("", "Error : " + e.getMessage());
                }
                for (DocumentChange doc : documentSnapshots.getDocumentChanges()) {
                    if (doc.getType() == DocumentChange.Type.ADDED) {
                        Log.d("Brand Name: ", doc.getDocument().getId());
                        doc.getDocument().getReference().collection("SubBrands").addSnapshotListener(new EventListener<QuerySnapshot>() {
                            @Override
                            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
                                if (e != null) {
                                    Log.d("", "Error : " + e.getMessage());
                                }
    
                                for (DocumentChange doc : documentSnapshots.getDocumentChanges()) {
                                    if (doc.getType() == DocumentChange.Type.ADDED) {
                                        Log.d("SubBrands Name: ", doc.getDocument().getId());
                                    }
                                }
    
                            }
                        });
                    }
    
                }
            }});
    

    注意:我已经更新了答案。很明显,您无法通过单个请求获取集合文档中的子集合。

    【讨论】:

    • 我知道这个,但在这里我需要品牌列表和子品牌。所以,我的问题是如何在集合“咖啡”中检索它们。希望我现在清楚了。
    • 对于您的场景,您必须在 for 循环中单独获取子品牌。
    • 能否请您编辑代码并说明如何操作?就我而言, parent 应该是 Coffee 集合并遍历里面的子品牌。有可能吗?
    • 真的很抱歉这对我来说并不明显。但是嗯..这种方法有什么作用?它现在看起来与我的问题中的代码相同。
    • 方法的目的是获取咖啡的id并获取其子品牌。
    【解决方案2】:

    我知道这已经是一个公认的答案,但我想为您提供一种更优雅的方式来构建您的数据库。这意味着您还可以更轻松地检索数据。在此之前,正如我从您的问题中了解到的那样,您只想检索数据,但为了实现这一点,只需使用 get() 调用。 addSnapshotListener() 用于检索real time 数据。

    这是我建议您用于应用的数据库结构:

    Firestore-root
       |
       --- coffee (collection)
             |
             --- coffeeId (document)
                    |
                    --- coffeeBrand: "Nescafe"
                    |
                    --- coffeeSubBrand: "Sunrise"
                    |
                    --- coffeeName: "CoffeeName"
                    |
                    --- quantity
                           |
                           --- 50g: true
                           |
                           --- 100g: true
                           |
                           --- 150g: true
    

    虽然 Nouman Ch 的代码可能适用于您的实际数据库结构,但这种新结构将为您提供避免嵌套循环的能力。要获得所有的咖啡,只需使用以下代码:

    FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
    CollectionReference coffeeRef = rootRef.collection("coffee");
    coffeeRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                for (DocumentSnapshot document : task.getResult()) {
                    String coffeeName = document.getString("coffeeName");
                    Log.d("TAG", coffeeName);
                }
            }
        }
    });
    

    如果您只想显示Nescafe coffee,而不是使用CollectionReference,则需要使用Query

    Query query = coffeeRef.whereEqualTo("coffeeBrand", "Nescafe");
    

    如果您只想显示咖啡子品牌,请使用以下查询:

    Query query = coffeeRef.whereEqualTo("coffeeSubBrand", "Sunrise");
    

    如果你想显示咖啡品牌和子品牌,你可以像这样链接方法:

    Query query = coffeeRef
        .whereEqualTo("coffeeSubBrand", "Sunrise")
        .whereEqualTo("coffeeBrand", "Nescafe");
    

    如果您只想显示数量为100g 的咖啡,则只需使用以下查询:

    Query query = coffeeRef.whereEqualTo("quantity.100g", true);
    

    如果您想了解有关 Cloud Firestore 数据库结构的更多信息,可以查看我的 tutorials 之一。

    【讨论】:

    • 您提供的结构似乎与我需要的不同。咖啡可以有多个子品牌,每个子品牌都有数量和价格的键值对。在这种结构中,我需要获取所有子品牌及其各自的价格。
    • 我已经更新了我的答案,所以咖啡可以有多个子品牌。您可以为咖啡设置您想要的子品牌,然后对其进行查询。我给你提供quantity的地图作为例子,但它也可以像你说的那样持有一对数量和价格。
    • 我实际上同意@AlexMamo。对于未来的参考和查询他的 Db 结构的想法将更加有效。如果您预先知道节点的名称,甚至可能在 RealTimeDb 中,原始结构只会更好地工作......但对于 Firestore,以上是完美的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多