如何在 Firebase 实时数据库中搜索类似数组的数据?

Posted

技术标签:

【中文标题】如何在 Firebase 实时数据库中搜索类似数组的数据?【英文标题】:How to search by array-like data in Firebase Realtime Database? 【发布时间】:2021-03-02 23:25:42 【问题描述】:

我正在开发一个带有Firebase Realtime Database 设施的颤振应用程序。这是一种聊天应用程序。这里我有一个名为chat_room 的根节点,它将保存所有聊天室。每个chat_room 都将保存有关其成员的信息,即聊天中的人。下面是我现在的数据结构

我的要求是,当我通过电子邮件搜索时,我应该能够获得与该电子邮件关联的所有 chat_rooms。例如,我需要知道电子邮件 ID someone@test.com 注册的所有chat_rooms。

问题是,我现在知道我不能用我当前的结构来做到这一点,我将数据保存为array。阅读this 我知道使用SETArray 的更好替代品,因为它允许我们执行此类搜索。所以也许这就是我需要的结构。

 chat_room
      chatroom1
        chat_mode: "supplier",
        last_message: "test",
        timestamp: 1223334
        members:
            email1: true
            email2: true
      chatroom2
        chat_mode: "supplier",
        last_message: "test",
        timestamp: 1223334
        members:
            email1: true
            email2: true

下面是我用来通过电子邮件搜索的代码,它什么也没给我。

final DatabaseReference reference = FirebaseDatabase.instance.reference().child('chat_room');
reference.orderByChild("members").equalTo("someone@test.com").once();

目前,这是我将数据保存到 chat_room 的方式。

//Create chat_room
  Future<String> createChatRoom(String lastMessage, String chatMode, List<ChatMember> members) async 
    
    var newChatRoomRef = _chatRoomReference.push();
    var newChatRoomKey = newChatRoomRef.key;
    await newChatRoomRef.set(
      'last_message': lastMessage,
      'chat_mode': chatMode,
      'members': [members[0].email, members[1].email],
      'timestamp': DateTime.now().millisecondsSinceEpoch,
      
    );

    return newChatRoomKey;
  

无论是SET数据结构还是Array或者HashMap或者不管是什么,我的要求是通过电子邮件搜索chat_rooms。

    如果SET 数据结构是这个问题的答案,我怎样才能将它保存到firebase?如何准备数据以便正确发送?请随时使用我上面的createChatRoom 方法,并告诉我如何通过SET 而不是Array。 如何执行搜索? 如果set 不是答案,那是什么?

感谢您的支持。

编辑

根据@Frank 的建议,我这样写了我的代码,复制了他提供的确切代码。

//Create chat_room
  Future<String> createChatRoom(
      String lastMessage, String chatMode, List<ChatMember> members) async 
    var newChatRoomRef = _chatRoomReference.push();
    var newChatRoomKey = newChatRoomRef.key;
    await newChatRoomRef.set(
      'last_message': lastMessage,
      'chat_mode': chatMode,
      'members': [members[0].email, members[1].email],
      'timestamp': DateTime.now().millisecondsSinceEpoch,
    );
    var userChatRoomsRef =
        FirebaseDatabase.instance.reference().child('chat_room');
    members.forEach((member) 
      userChatRoomsRef
          .child(member.userID.toString() + "-userID")
          .child(newChatRoomKey)
          .set(true);
    );

    return newChatRoomKey;
  

那个,这是它生成的结构。 (请注意,30-userID 和 50-userID 是实际的用户 ID,因为我没有使用 Firebase Auth 的 UID)

无论如何,我真的不确定这是否是我应该拥有的正确结构。

编辑 2

根据@Frank 的编辑,这就是我制作我的代码和它生成的数据库结构的方式。

//Create chat_room
  Future<String> createChatRoom(
      String lastMessage, String chatMode, List<ChatMember> members) async 
    var newChatRoomRef = _chatRoomReference.push();
    var newChatRoomKey = newChatRoomRef.key;
    await newChatRoomRef.set(
      'last_message': lastMessage,
      'chat_mode': chatMode,
      'members': [members[0].email, members[1].email],
      'timestamp': DateTime.now().millisecondsSinceEpoch,
    );
    var userChatRoomsRef =
        FirebaseDatabase.instance.reference().child('user_chatrooms');
    members.forEach((member) 
      userChatRoomsRef
          .child(member.userID.toString() + "-userID")
          .child(newChatRoomKey)
          .set(true);
    );

    return newChatRoomKey;
  

现在仍然确定这是否是正确的,因为我现在正在转移到另一个节点。

【问题讨论】:

【参考方案1】:

是的,我在链接答案中给出的方法是允许搜索特定用户的聊天室。您最终会得到一个辅助数据结构,将用户映射到他们关联的聊天室。

为了保存这个额外的数据结构,你循环遍历子元素,基本上写出你已经拥有的相反的东西。比如:

var newChatRoomRef = _chatRoomReference.push();
var newChatRoomKey = newChatRoomRef.key;
await newChatRoomRef.set(
  'last_message': lastMessage,
  'chat_mode': chatMode,
  'members': [members[0].email, members[1].email],
  'timestamp': DateTime.now().millisecondsSinceEpoch,  
);
var userChatRoomsRef = FirebaseDatabase.instance.reference().child('user_chatrooms')
members.forEach((member) 
  userChatRoomsRef.child(member.uid).child(newChatRoomKey).set(true);
);

【讨论】:

感谢您的回复。我更改了我的代码。它生成的代码和数据库结构都在我编辑的问题中。我真的不确定这是否是您想要生成的。请检查。 糟糕。正如我对您链接的问题的回答中所解释的那样,那应该是一个不同的***节点。我更新了答案中的代码。 我已经对我的代码进行了编辑,在我编辑的答案中发布了数据库结构和代码。在那里,您似乎创建了一个名为user_chatrooms 的新node。但我仍然看不到通过电子邮件搜索聊天的方法。这是对的吗?或者我必须通过用户 ID 搜索 user_chat 房间才能找到相关的聊天室?那也很好。请指教。 啊,如果你想通过电子邮件访问它们,你需要使用(编码的)电子邮件作为密钥,而不是我上面使用的 UID。好吧...或者将电子邮件存储为值,而不是像我在回答中所做的那样true 完美。谢谢。

以上是关于如何在 Firebase 实时数据库中搜索类似数组的数据?的主要内容,如果未能解决你的问题,请参考以下文章

Swift:为用户搜索 Firebase 数据库

如何从 Firebase 中的实时数据库中获取数组

Firebase 实时数据库在查询之间按单词搜索?

如何在 Swift 中保存实时 Firebase 数据库中的数据?

Firebase Swift - 当搜索控制器过滤结果时,实时更新不起作用

如何使用NodeJS中的firebase云功能从firebase实时数据库中找出最近的位置LatLng