使用Firebase中的“关联”数据

时间:2017-09-30 19:49:04

标签: android firebase firebase-realtime-database

我对Firebase数据库相对较新,直到现在才使用MySQL。我知道Firebase中没有“关联”数据,但我认为我仍然在尝试创建它,因为这就是我的思维方式!所以,我可能遇到的问题是因为我的数据格式很糟糕 - 我很感激任何指针。

在我的应用中(使用Android Studio),每个用户都可以拥有多个Box。每个Box使用单个调色板(可以是默认调色板,也可以是用户定义的调色板)。调色板由许多颜色组成。

目前,我的数据是这样的:

Boxes
   BoxKey1
      name: Test Box
      paletteKey: paletteKey1
      belongsTo: userKey1
   BoxKey2
      ... etc ...
Colours
   ColourKey1
       name: Red
       hexCode: ff0000
   ColourKey2
       name: Blue
       ... etc ...
Palettes
   PaletteKey1
       name: default
       colours
           ColourKey1: true
           ColourKey7: true
           ... etc ...
   PaletteKey2
       ... etc ...
Users
   UserKey1
      name: Joe Bloggs
      boxes
          BoxKey1: true
          BoxKey5: true
   ... etc ...

因此,我可以轻松地检索用户Box的列表,并列出所有名称。如果用户单击名称,则会检索并显示具有该名称的Box。我还需要显示使用的Palette(它包含的名称和颜色)。

在活动中,我按如下方式检索Box:

    mBox.setKey(boxKey);
    mBox.initialiseBox(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            mBox = dataSnapshot.getValue(Box.class);
            boxName.setText(mBox.getName()); // Show Box name
// AT THIS POINT I HAVE THE BOX DETAILS, BUT I NEED THE PALETTE DETAILS TOO
        }
    });

在Box类中,initialiseBox如下所示:

public void initialiseBox(ValueEventListener listener) {
    if(this.key == null) return;
    DatabaseReference mBoxReference = FirebaseDatabase.getInstance().getReference()
            .child("boxes").child(this.key);
    mBoxReference.addListenerForSingleValueEvent(listener);
}

这工作正常,但此时我只从数据库中检索了Palette键以及其他Box数据。然后我如何得到实际的调色板及其所有颜色,所以我也可以显示它们?

我一直在尝试在主要活动中像这样做一种'嵌套式监听器':

    mBox.initialiseBox(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            // Same as before
            mBox = dataSnapshot.getValue(Box.class);
            boxName.setText(mBox.getName()); // Show Box name

            // Now add a new listener for the Palette
            mPalette.setKey(mBox.getPaletteKey());
            mPalette.initialisePalette(new ValueEventListener() {
                 @Override
                 public void onDataChange(DataSnapshot dataSnapshot) {
                      mPalette = dataSnapshot.getValue(Palette.class);
                      paletteName.setText(mPalette.getName());

                 }
            });
        }
    });

但它似乎非常笨拙,而且我不能完全使用它(Palette没有填充,所以在paletteName.setText位我得到一个错误。)

这是正确的方法吗?如果没有,我该怎么办?如果这是正确的想法,谁能看到我出错的地方?

1 个答案:

答案 0 :(得分:1)

Firebase(以及许多其他NoSQL数据库)中的相关数据几乎与SQL数据库中的相同。主要区别是:

  1. 在Firebase中,DBMS不会为您管理关系。这意味着您需要编写自己的代码(以及可能的服务器端安全规则),以确保关系保持一致。
  2. 您经常会复制Firebase中的部分数据,从而减少了查找的需求。但这需要在写入期间需要复制数据,并且您需要考虑strategies for keeping the duplicated data up to date
  3. 您正在做的事情称为客户端连接,这确实是将不同顶级节点的数据导入您的应用程序的有效方法。

    使用嵌套侦听器执行此操作是否最佳方法取决于数据和用例。这里要考虑的事情:

    1. 如果目标列表很短,您可能只想预先加载整个列表并删除嵌套连接的需要。
    2. 加入项目需要什么?如果它只是一个属性(例如调色板的名称),请考虑是否值得在源下复制该属性以消除对嵌套连接的需要。
    3. 嵌套代码将很快变得难以理解。将监听器拉出到实用程序类中,并使用更简单的接口调用它。 即,您可能希望集中错误处理,您可以在帮助程序类中完美地执行此操作。这将为您提供一个回调方法,可以在Java 8中进行lambdafied - 使其更容易阅读。
    4. 我经常建议您在Firebase中为应用的屏幕建模。因此,如果您的应用程序具有用户名列表,请在数据库中建模用户名列表。此时您还将框ID放在该列表下,这意味着您最终将为所有用户加载框ID,只是为了显示其名称。
    5. 我强烈建议您阅读NoSQL data modeling并观看Firebase for SQL developers