Firebase一对一聊天应用程序结构和按值获取子级

Firebase一对一聊天应用程序结构和按值获取子级,firebase,firebase-realtime-database,nosql,Firebase,Firebase Realtime Database,Nosql,我尝试用firebase和angular构建一对一聊天应用程序。我正在使用firebase文档中推荐的结构,但我在数据检索方面遇到了麻烦 { "chats" : { "one" : { "lastMessage" : "test" } }, "members" : { "one" : { "rebel" : true, "redboy" : true } }, "messages" : { "one"

我尝试用firebase和angular构建一对一聊天应用程序。我正在使用firebase文档中推荐的结构,但我在数据检索方面遇到了麻烦

{
  "chats" : {
    "one" : {
      "lastMessage" : "test"
    }
  },
  "members" : {
    "one" : {
      "rebel" : true,
      "redboy" : true
    }
  },
  "messages" : {
    "one" : {
      "-KS1R6b-1TdVASQL4tj7" : {
        "createdAt" : 1474288450158,
        "text" : "hgagagagaga",
        "userId" : "rebel"
      },
      "-KS1aZxqX3_PpjNdyiA7" : {
        "createdAt" : 1474291191857,
        "text" : "hhh",
        "userId" : "redboy"
      }
    }
  }
}
如何使用firebase查询获取用户“叛军”聊天记录。或者我应该在用户的根目录上存储聊天ID

没有
WHERE
子句,这种结构使我感到困惑

更新:

如果我将chatIds添加到用户的根目录,这可以解决我的问题,但不能确定它是否正确。看来是对的

"users" : {
    "rebel" : {
      "age" : 3,
      "chats" : {
        "one" : true
      },
      "name" : "rbl"
    },
    "redboy" : {
      "age" : 5,
      "chats" : {
        "one" : true
      },
      "name" : "rb"
    }
  }

是的,您需要将聊天id存储在用户的根目录下,其值为true,以检索所有聊天记录以及随后的消息。在使用Firebase(以及大多数其他NoSQL解决方案)时,请遵循此原则,您会发现您经常需要按照应用程序使用数据的方式对数据进行建模

您当前的数据结构允许您轻松找到特定聊天室的成员

从技术上讲,您可以查询以查找特定成员的聊天室:

ref.child('members').orderByChild('rebel').equalTo(true)
但这需要为每个用户定义一个索引,该索引不可伸缩(因为必须为每个用户手动添加索引):

最常见的解决方案是(如前所述)对数据进行建模,以允许进行所需的查询。由于要查找每个用户的聊天室,因此应展开模型以存储每个用户的聊天室:

{
  "rules": {
    "members": {
      ".indexOn": ["rebel", "redboy"]
    }
  }
}
"memberships" : {
  "rebel" : {
    "one": true
  },
  "redboy" : {
    "one" true
  }
},
如您所见,这里我们保留
成员的反向索引

现在,您可以通过以下方式轻松确定用户的房间:

ref.child('memberships/rebel').on('child_added', ...
我看到你在你的问题中增加了一个类似的结构。主要区别在于我将其添加为顶级结构。这是Firebase的常见模式,因为它可以更容易地保护数据并仅检索数据的一个子集


为了更好地理解这一点,我推荐这篇文章。

您的问题中包含了JSON树的图片。请将其替换为实际的JSON作为文本,您可以通过单击Firebase数据库控制台中的导出按钮轻松获得该文本。将JSON作为文本使其具有可搜索性,允许我们轻松使用它来测试您的实际数据,并在我们的答案中使用它,一般来说,这是一件好事。@FrankvanPuffelen您是对的,我将其替换为Hanks Frank这对我来说是一个非常好的答案,我将把我的添加到顶层,因为你建议我这里有一个关于@FrankvanPuffelen的后续问题,当用户redboy想要向rebel发送消息时会发生什么?redboy会先创建一个新聊天,然后将该聊天添加为memberships/rebel中的节点吗?这是正确的方法吗?所有这些逻辑都会放在客户端应用程序中吗?