从父节点检索子对象

时间:2016-12-18 23:21:31

标签: android firebase firebase-realtime-database

所以我遵循了我认为最新的Firebase建议来构建扁平数据库,如下所示:

enter image description here

类别和子类别是单独的节点,其中的类别引用了子类别SubCategories的键。

然后,我希望能够基于Categories键运行查询并返回其子子类别。

我的代码基于这个(过时的)示例,这是我能找到的唯一示例 - 来自https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html

var commentsRef = new Firebase("https://awesome.firebaseio-demo.com/comments");
var linkRef = new Firebase("https://awesome.firebaseio-demo.com/links");
var linkCommentsRef = linkRef.child(LINK_ID).child("comments");
linkCommentsRef.on("child_added", function(snap) {
  commentsRef.child(snap.key()).once("value", function() {
    // Render the comment on the link page.
  ));
});

并尝试将其转换为在Android上运行,并且最佳猜测替代上述示例中不再存在的方法:

final DatabaseReference subCategoriesRef = FirebaseDatabase.getInstance().getReference("users").child(user.getUid()).child("SubCategories");
    DatabaseReference categoriesRef = FirebaseDatabase.getInstance().getReference("users").child(user.getUid()).child("Categories");
    Query categoriesSubCategoriesRef = categoriesRef.child(EXTRA_CATEGORY_KEY).child("SubCategories");
    categoriesSubCategoriesRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            subCategoriesRef.child(dataSnapshot.getKey());
            subCategoriesRef.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {

                    //Log.v("item", dataSnapshot.child("SubCategories").child("SubCategoryName").getValue().toString());
                }
                @Override
                public void onCancelled(DatabaseError databaseError) {
                }
            });
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });

种类有效,但它会返回SubCategories的全部,而不仅仅是那些使用EXTRA_CATEGORY_KEY指定的类别I的子类,然后它返回作为Json对象:

DataSnapshot { key = SubCategories, value = {-KZ8aQOhk1r7tj5gjM97={
Description=, isChecked=false, ID=103, Published=1, SubCategoryName=Name1, hasExtra=false, Deleted=0, CategoryID=8}, 
-KZ8aQP98TujvnjAERXF={Description=, isChecked=false, ID=40, Published=1, SubCategoryName=Name2, hasExtra=false, Deleted=0, CategoryID=2},...

......等等。

首先:我的数据结构是否正确,还是我遵循了不推荐的建议?其次:我的查询有什么问题?

编辑:这是数据库的当前(不正确)完整结构。每个用户都是私人用户,他们无法与任何其他用户共享任何数据。

{
  "users": {
    "Uc6PJMfq5VZpT2V7EHMmmGPk0Zv2": {
  "Categories": {
    "-KZ8aQPi5QXrFv_RrKIh": {
      "CategoryName": "",
      "Constant": "",
      "Deleted": 0,
      "Description": "",
      "ID": 1,
      "Published": 1,
      "Sequence": 1,
      "SubCategories": {
        "-KZ8aQPHbCTtveAfR_D8": true,
        "-KZ8aQPHbCTtveAfR_D9": true
      }
    }
  },
  "SubCategories": {
    "-KZ8aQPHbCTtveAfR_D8": {
      "CategoryID": 1,
      "Deleted": 0,
      "Description": "",
      "ID": 1,
      "Published": 1,
      "SubCategoryName": "",
      "hasExtra": false,
      "isChecked": false
    },
    "-KZ8aQPHbCTtveAfR_D9": {
      "CategoryID": 1,
      "Deleted": 0,
      "Description": "",
      "ID": 21,
      "Published": 1,
      "SubCategoryName": "",
      "hasExtra": false,
      "isChecked": false
    }
  },
  "journal": {
    "-KYzQOrMrEenlXobzG3d": {
      "entry": "Test entry",
      "entryDate": {
        "date": 14,
        "day": 3,
        "hours": 22,
        "minutes": 22,
        "month": 11,
        "seconds": 5,
        "time": 1481754125034,
        "timezoneOffset": 0,
        "year": 116
      },
      "id": "",
      "source": "journal"
    }
  },
  "userDetails": {
    "email": "",
    "username": ""
  }
},
"anotheruniqueuser": {
  "Categories": {
  },
  "SubCategories": {        
  },
  "journal": {
  },
  "userDetails": {
    "email": "",
    "username": ""
  }
}
  }
}

1 个答案:

答案 0 :(得分:0)

您复制的示例代码段会侦听child_added事件,该事件将转换为Java中的ChildEventListener.onChildAdded

该片段变为:

DatabaseReference categoriesRef = FirebaseDatabase.getInstance().getReference("Categories");
DatabaseReference subCategoriesRef = categoriesRef.child(user.getUid()).child("SubCategories");
DatabaseReference categoriesRef = categoriesRef.child(user.getUid()).child("Categories");
DatabaseReference categoriesSubCategoriesRef = categoriesRef.child(EXTRA_CATEGORY_KEY).child("SubCategories");

categoriesSubCategoriesRef.addChildEventListener(new ChildEventListener() {    
    @Override
    public void onChildAdded(DataSnapshot keySnapshot, String previousChildKey) {
        subCategoriesRef.child(keySnapshot.getKey());
        subCategoriesRef.addSingleValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.v("item", dataSnapshot.child("SubCategories").child("SubCategoryName").getValue().toString());
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    });

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
        // ...
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {
        // ...
    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
        // ...
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw dataError.toException();
    }
});

一些评论:

  • 代码段中唯一不再存在的方法是new Firebase("https://awesome.firebaseio-demo.com/links"),转换为FirebaseDatabase.getInstance().getReference("links")
  • 您似乎在代码中随意混合用户和类别。充其量是令人困惑的,但更可能是错误的。我尽力理解上面代码中的混合,但很可能失败了。
  • 每个用户下都有多种类型的数据。要遵循Firebase文档中的最佳做法,请将类别的元数据(如名称,描述,数字ID等内容)与其层次结构的构建分开。

    Categories
        category1
            name: ...
            description: ...
        category2
            name: ...
            description: ...
        category3
            name: ...
            description: ...
    Parents
        category2: category1
        category3: category1
    Children
        category1
            category2: true
            category3: true