缺少Firebase节点元数据(one2one聊天应用)

时间:2016-11-16 01:15:05

标签: android firebase firebase-realtime-database

我正在尝试创建“针对Android的一对一Firebase数据库聊天”。到目前为止,正在使用下面的结构。大字符串表示user_TO_user,KW记录是聊天消息。

chat
  D_57f337e7e55df9ca167d0421_TO_O_57f337e7e55df9ca167d0421
    -KWd06dvkmcoCJd6fNWs
    -KWd7yBoUy-RkEJAlVOB
    -KWd8Au5bPAwMsx3gYhp
    ....
  O_57f337e7e55df9ca167d0421_TO_D_57f337e7e55df9ca167d0421
    -KWd06da-Cx0qjnPUE3l
    -KWd7yBvyLoLd2fiBcia
    -KWd8Au3A_5FJZS8S0qz
    ....

在显示特定用户对话列表的Android活动中,我创建了一个ListView并从Firebase中读取列表:

    String calculated = "O_57f337e7e55df9ca167d0421";    // calculated userId
    firebase_chat.orderByKey().startAt(calculated).endAt(calculated + "\uf8ff").addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s)        
        {
            // add item to list adapter

        }

}

这很好。

但我在这里有两个问题。

第一即可。我需要制作具有反向名称的节点的副本(如上所示,即A_TO_B和B_TO_A),以允许参与聊天的两个用户使用Firebase数据库查询功能(因为substring()或contains()不是Firebase中的可用过滤器)。有没有更好的查询方法阻止我复制所有消息?是否有任何节点别名

第二即可。节点名称本身有助于代码识别聊天名称....但它对用户表示没有任何帮助。我需要将某个用户O_57f337e7e55df9ca167d0421与“John Smith”关联起来,以便在屏幕上显示John Smith。此机制应该应用于每个会话节点。

我在考虑使用每个节点中的第一条记录来存储节点元数据,因此,在获取节点名称后,我可以从Android设备查询DataSnapshot以查找有关此节点的信息。但是,我担心这会触发每个会话节点的新后端(Firebase DB)请求以获取其元数据,这可能效率不高并导致来自每个设备的服务器调用过多。正确的解决方案是在每个节点的名称中加入元数据 ...所以我可以保存第二次调用....但这在Firebase中似乎不可行。

你是否想出更有效的方法?

由于

更新:所以,根据vzsg的回答,更好的结构可能是:

  • 封邮件
    • A_TO_B
      • MSG1
      • MSG2
      • Msg3的
    • A_TO_C
      • MSG1
      • MSG2
      • Msg3的
    • A_TO_J
      • MSG1
      • MSG2
      • Msg3的
  • 聊天
      • A_TO_B
      • A_TO_C
        • C
      • A_TO_J
        • Ĵ
      • A_TO_B
        • A
    • Ç
      • A_TO_C
        • A
    • Ĵ
      • A_TO_J
        • A

这将允许:

  • 在打开对话屏幕时创建聊天条目

  • 在第一条消息上创建一个msgs条目

  • 查询聊天/节点查找用户的对话,包括其他用户的数据

  • 查询msgs / A_TO_B节点以获取会话的实际消息

(我会稍等一下接受你的回答,但我喜欢这个提议)

update2:或简化聊天节点:

  • 聊天
      • C
      • Ĵ
      • A
    • Ç
      • A
    • Ĵ
      • A

并以对话方式撰写会话名称以获取消息

我在此描述的最终解决方案:https://github.com/cvivek07/Firebase_Chat/issues/1#issuecomment-260925121

2 个答案:

答案 0 :(得分:2)

第一

有一种非常简单的方法可以避免重复:在计算组合ID时按字典顺序对两个用户ID进行排序。 这样,无论哪个用户正在寻找另一个用户,他们都会找到一个单一的对话而你不必跳过篮球。

E.g:

  • A到B变为A_to_B
  • B到A变为A_to_B

也就是说,没有任何查询选项可以提供帮助,并且根本不支持别名节点。

第二

您有两种不同的利弊选择:

  1. 将参与者用户名复制到聊天节点中,即您创造的“正确解决方案”。它不一定是真的,但它是可行的:存储是便宜的,并且消除额外的查询使客户端代码更简单。但是,当用户更改其名称时,拥有副本会导致问题 - 所有相关的聊天节点也应该更新。

  2. 将用户节点保留在其他位置,并懒惰地获取它们以加载用户名(以及可能的其他配置文件数据,如图片URL)。显示列表变得更难实现,但只需要在一个地方进行更新 您不必担心“服务器请求太多”,但这是SDK可以轻松处理的内容。您还可以在内存中缓存已知用户。

  3. 这两种解决方案都在实践中运行,您必须确定哪种策略在您的方案中更有效。

    附加

    所呈现的架构存在严重缺陷:当您使用chat节点列出会话然后列出其下的消息时,客户端必须下载所有内容,包括每条消息都没有界限,浪费了大量的CPU时间和带宽。

    您应该考虑单独存储会话列表和消息;一般而言,旨在建立平坦的数据库结构。

答案 1 :(得分:1)

添加一些代码以支持 vzsg

创建的第1点
{{1}}

最终为聊天室中的参与者制作一个UID