Firebase 数据结构,订阅引用的对象

Posted

技术标签:

【中文标题】Firebase 数据结构,订阅引用的对象【英文标题】:Firebase data structure, subscribing to referenced objects 【发布时间】:2016-05-17 16:21:46 【问题描述】:

从我读过的关于在 Firebase 中保留“引用”的文章(1、2、3)中,我无法理解哪个是引用其他对象的最佳方式,如果我们需要监听所有引用对象的属性

数据:

我有一些用户,当他们加入锦标赛时,他们可以扮演玩家的角色:

"t_3515":  
   "entry_fee":100,
   "status":"Cancelled",
   "players":  
      "p_3":  
         "player_name":"User A",
         "score":"0",
         "status":"Waiting"
      ,
      "p_4":  
         "player_name":"User B",
         "score":"0",
         "status":"Accepted"
      
   

我有一个包含系统所有锦标赛的列表。

我必须如何显示这些数据:

一个屏幕显示/收听“所有”锦标赛列表。 一个屏幕显示/收听登录用户所属的锦标赛。

我正在寻找最佳方式(就性能而言)来构建满足这两个要求的数据。


可能的解决方案 1:

为每个玩家复制每个锦标赛,这意味着:

使用 firebaseURL//tournaments 访问用户的比赛,使客户可以轻松地将其显示在列表中。 (好!) 每个完整的锦标赛都将复制到每个玩家的 URL 中。 (不好?)

可能的解决方案 2:

Follow this approach,表示:

要访问用户的锦标赛,客户端应订阅 firebaseURL//锦标赛(了解何时添加/删除锦标赛),然后遍历每个锦标赛,查找其原始数据的 URL,并订阅它。 (可怕) 比赛的数据将只保存在一个地方。 (好)

理论上,这个应用程序将有成千上万的锦标赛和用户,我想如果我们最终像解决方案 1 那样复制数据,请记住这一点。

【问题讨论】:

为什么要保留参考文献?如果您正在观察一个节点,它会告诉您是否有任何更改。例如; User_A 已登录并查看所有锦标赛屏幕(正在观察锦标赛节点)。 User_B 开始了一个新的锦标赛。 User_A 将自动收到该事件的通知,以便您可以更新他们以显示它。如果 User_A 然后切换到“我的锦标赛”屏幕,那是代码中的一个简单过滤器,仅显示他们参与的锦标赛。挑战在于构建 Firebase 数据。你能用你想对参考做些什么来更新你的问题吗? @Jay ,“切换到我的锦标赛屏幕,这是一个代码中的简单过滤器,仅显示他们参与的锦标赛”。我目前正在观察所有锦标赛的 url,当切换到“我的锦标赛”时,我会遍历它们以获取用户参与的那些,但在 iosandroid 上它变得非常慢,因为有数百个锦标赛.您是否建议使用 Firebase Query 进行操作?我需要实时更新“我的锦标赛”,这就是为什么我需要订阅每个用户的锦标赛。 虽然从技术上讲,您可以使用 Firebase 执行此操作,但需要做很多额外的工作,并且循环非常低效。使用 NSPredicate 进行过滤,结果是您想要的锦标赛数组,然后使用该数组更新您的 tableView。 NS 谓词将在几分之一秒内过滤数千个索引。请参阅此Question about NSPredicate。尝试编写一些代码以使用 NSPredicate 进行过滤,如果遇到困难,请告诉我们,以便我们提供帮助。 谢谢@Jay,但我同时使用Android和iOS,现在我不是在客户端寻找解决方案,我认为必须有一个正确的方法来解决这个问题而不依赖每个客户端的实现。 【参考方案1】:

有很多解决方案,但这里有一个非常简单:

鉴于以下 Firebase 结构(为了简化,省略了分数)

tournaments
  t_3515 
    entry_fee:100
    status:Active
    players  
      p_3: true
      p_4: true
    status
      P_3: waiting
      P_4: accepted
    
  

1) 一个屏幕显示/收听“所有”锦标赛列表。

当用户在观察所有锦标赛的屏幕上时,请执行以下操作。

ref = tournaments

ref.observeEventType(.Value, withBlock:  snapshot in
    print(snapshot)
    //note that Value returns the entire contents of the node so this is not
    //  the best approach. It's here for conceptual. See note below.
)

这将通知应用程序任何在锦标赛中发生变化的节点

2) 一屏显示/收听登录用户所属的锦标赛。

当用户在屏幕上只观察他们参加的锦标赛时,请执行以下操作:假设用户是 p_3 并且想查看他们参加的锦标赛:

ref = tournaments

ref.queryOrderedByChild("players/p_3").queryEqualToValue(true)
        .observeEventType(.Value, withBlock:  snapshot in
    print(snapshot)
)

画面切换时,先停止观察。

ref.removeAllObservers

现在,深入一点,您可能不想使用 .Value 来附加您的观察者。 .ChildAdded、.ChildChanged 和 .ChildRemoved 将为您提供更好的粒度级别,了解实际发生的情况。

【讨论】:

以上是关于Firebase 数据结构,订阅引用的对象的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 数据库数据检索在空对象引用上给出 NullPointerException 'java.lang.String java.lang.Object.toString()'

Vue.js firebase 实例 - 用户 UID 作为数据库引用

在 Angular 中拉取和订阅 firebase 数据

离子生命周期取消/订阅 Firebase 数据库流(使用异步管道)

Angular 5,订阅firebase,第一个元素是undefined

避免在循环中使用嵌套的可观察订阅的正确方法是啥?