Firebase - 通过up-votes和条目进行多次过滤,标记为" read"

时间:2017-08-07 18:43:35

标签: firebase firebase-realtime-database filtering

我知道这个问题已经被问了很多次,而且我知道不同的解决方法,但是我无法找到将这些解决方法应用到我的问题的好方法。

我正在构建一个与Firebase集成的应用程序,它具有故事的概念。我希望应用程序能够检索通过向上投票排序的故事(到目前为止没什么大不了的。)

stories
  <some-story-id-1>
    id: "<some-story-id-1>"
    published: true
    title: "Test"
    userId: "<some-user-id>"
    points: 12

但是我还希望标记个别用户何时阅读故事,以便他们不会再次向他们展示该故事。

所以我通常希望丰富我的用户数据,类似于下面的内容。

users
  <some-user-id>
    stories-read
      <some-story-id-1>: true
      <some-story-id-2>: true

因此,我需要检索故事的分页结果,按照向上排序排序,排除已被用户标记为 read 的故事。

现在我可以通过向上投票检索仅订购的数据,然后在客户端省略标记为 read 的故事,但这是对数据的极大浪费(考虑到这是谷歌向人们收费的方式,最终可能会花费很多钱)。

有没有更好的方法来实现相同的行为而不浪费数据?

1 个答案:

答案 0 :(得分:2)

这是一个非常好的想法&amp;设计问题

有许多解决方案,但您可以在其中跟踪用户读取的消息。

给定结构

messages
  msg_0
    msg: "Some message
    read_by:
      user_0: true
      user_1: true
  msg_1
    msg: "Another message"
    read_by:
      user_2: true
  msg_2
    msg: "Yipee"
    read_by
      user_1: true

让我们假设我们想要获取user_0未读取的所有消息,在本例中为1和2。

我不知道你的平台,但这是我们在Swift中的表现。

let ref = self.ref.child("messages")
let query = ref.queryOrdered(byChild: "read_by/user_0").queryEqual(toValue: nil)
query.observeSingleEvent(of: .value, with: { (snapshot) in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        print(snap)
    }
})

返回

Snap (msg_1) {
    msg = "Another message";
    "read_by" =     {
        "user_2" = 1;
    };
}
Snap (msg_2) {
    msg = "Yipee";
    "read_by" =     {
        "user_1" = 1;
    };
}

所以我们正在做的是在没有user_0(nil)的情况下查询所有子read_by节点的Firebase,这是用户没有读过的。

当user_0读取它时,只需将user_0:true添加到消息的read_by节点。

修改

以上只是部分解决方案,省略了投票排序。让我再试一次,提供一个完整的解决方案。鉴于结构

users
  uid_0
    name: "Biff"
    unread_messages
       msg_0001:
           votes: -10
       msg_0005:
           votes: -20
       msg_0022:
            votes: -5
  uid_1
    name: "Henry"
    unread_messages
       msg_0003:
           votes: -4
       msg_0009:
           votes: -2

然后读取uid_0未读取的消息,我们执行以下操作

var messageKeys = [String]()

func getUnreadMessages() {

    let ref = self.ref.child("users").child("uid_0/unread_messages")
    let query = ref.queryOrdered(byChild: "votes")
    query.observeSingleEvent(of: .value, with: { (snapshot) in
        for child in snapshot.children {
            let snap = child as! DataSnapshot
            let key = snap.key
            self.messageKeys.append(key)
        }
    })
}

上面的代码引用了按投票排序的未读消息(密钥)。请注意,投票数存储为负值,将按降序读取它们。作为替代方案,将它们保存为正值并将数据中的键和数量存储在一起(例如,作为类数组)并在代码中对数组进行排序。

然后收到消息:

for msgKey in messageKeys {
   let ref = self.ref.child("messages").child(msgKey)
   ref.observeSingleEvent(of: .value, with: { (snapshot) in
       let msgDict = snapshot.value as! [String: Any]
       let msg = msgDict["msg"] as! String
       print(msg)
   })
}