当前位置: 首页 > 面试题库 >

Firebase查询child的child是否包含值

关冠宇
2023-03-14
问题内容

该表的结构为:

  • chats
  • –> randomId
  • –>–> participants
  • –>–>–> 0: ‘name1’
  • –>–>–> 1: ‘name2’
  • –>–> chatItems

等等

我想做的是查询聊天表,以通过传入的用户名字符串查找所有持有参与者的聊天。

这是我到目前为止的内容:

 subscribeChats(username: string) {
    return this.af.database.list('chats', {
        query: {
            orderByChild: 'participants',
            equalTo: username, // How to check if participants contain username
        }
    });
 }

问题答案:

您当前的数据结构非常适合查找特定聊天的参与者。但是,这不是一个很好的反向搜索结构:用户参与的聊天。

这里有几个问题:

您正在将集合存储为数组
您只能在固定路径上建立索引

设置与数组

聊天可以有多个参与者,因此您将其建模为数组。但这实际上不是理想的数据结构。每个参与者可能只能聊天一次。但是通过使用数组,我可以拥有:

participants: ["puf", "puf"]

显然这不是您要考虑的,但是数据结构允许这样做。您可以尝试在代码和安全规则中对此进行保护,但是如果您从一个隐式地与您的模型更好地匹配的数据结构开始,这将更加容易。

我的经验法则:如果发现自己正在写作array.contains(),则应该使用set。

集合是每个孩子最多可以出现一次的结构,因此自然可以防止重复。在Firebase中,您可以将集合建模为:

participants: {
  "puf": true
}

在true这里其实只是一个伪值:重要的是我们搬到名称的关键。现在,如果我尝试再次加入此聊天,那就没问题了:

participants: {
  "puf": true
}

当您加入时:

participants: {
  "john": true,
  "puf": true
}

这是您需求的最直接表示:一个集合,每个参与者只能包含一次。

您只能索引已知属性

通过上述结构,您可以查询您所在的聊天室:

ref.child("chats").orderByChild("participants/john").equalTo(true)

问题是,这需要您在`participants / john“上定义索引:

{
  "rules": {
    "chats": {
      "$chatid": {
        "participants": {
          ".indexOn": ["john", "puf"]
        }
      }
    }
  }
}

这将工作并表现出色。但是现在,每次有新朋友加入聊天应用程序时,您都需要添加另一个索引。显然,这不是可扩展的模型。我们需要更改数据结构以允许您需要的查询。

反转索引-向上拉类别,使树变平
经验法则:为数据建模以反映您在应用程序中显示的内容。

由于您要显示用户的聊天室列表,因此请存储每个用户的聊天室:

userChatrooms: {
  john: {
    chatRoom1: true,
    chatRoom2: true
  },
  puf: {
    chatRoom1: true,
    chatRoom3: true
  }
}

现在,您只需使用以下命令即可确定您的聊天室列表:

ref.child("userChatrooms").child("john")

然后遍历键以获取每个房间。

您将在应用程序中有两个相关列表:

特定用户的聊天室列表
特定聊天室的参与者列表
在这种情况下,您还将在数据库中同时拥有两个列表。

chatroomUsers
  chatroom1
    user1: true
    user2: true
  chatroom2
    user1: true
    user3: true
userChatrooms
  user1:
    chatroom1: true
    chatroom2: true
  user2:
    chatroom1: true
  user2:
    chatroom2: true

由于Firebase建议不要嵌套数据,因此我将两个列表都拉到了树的顶层。

在NoSQL解决方案中拥有两个列表是完全正常的。在上面的示例中,我们将其userChatrooms称为的倒排索引chatroomsUsers。

Cloud Firestore

这是Cloud Firestore对此类查询提供更好支持的情况之一。它的array-contains运算符允许过滤器在数组中具有特定值的文档,而arrayRemove允许您将数组视为一组。



 类似资料:
  • 表的结构是: null 以下是我目前掌握的信息:

  • 移除子节点。 参数 名称 类型 默认值 描述 child zrender.Element 待移除的元素。 相关 zrender.Group.add、 zrender.Group.removeAll。

  • 添加子节点到最后。 参数 名称 类型 默认值 描述 child Element 待添加的元素。 返回值 this。 相关 zrender.Group.addBefore、zrender.Group.remove。

  • 描述 (Description) :first-child伪类用于向一个元素添加特殊效果,该元素是某个其他元素的第一个子元素。 要使:IE中的第一个孩子工作必须在文档顶部声明。 请注意 - 伪类名称不区分大小写。 伪类与CSS类不同,但它们可以组合在一起。 例子 (Example) 例如,要缩进所有元素的第一段,您可以使用此定义 - <html> <head> <style ty

  • 问题内容: 说我有一张这样的表: 如何才能以这种格式对结果进行实际排序?即由父级->子级->子子级命令,根据我只要求说最多5个级别?我已经研究了“嵌套集模型”,但是对于我的要求而言,它似乎太复杂了。我不确定的是真正理解了可用于显示如上所示结果的SQL查询,或者在这种情况下,我应该使用像PHP这样的服务器端语言来帮我吗? 问题答案: 您可以尝试以下方法: 如果层次结构是有限的,则不需要递归查询。 o

  • 添加子节点到 nextSibling 之前。 参数 名称 类型 默认值 描述 child Element 待添加的元素。 nextSibling Element 已经在 Group 中的元素。 返回值 this。 相关 zrender.Group.add、zrender.Group.remove。