我知道这个问题已经被问了很多次,而且我知道不同的解决方法,但是我无法找到将这些解决方法应用到我的问题的好方法。
我正在构建一个与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 的故事,但这是对数据的极大浪费(考虑到这是谷歌向人们收费的方式,最终可能会花费很多钱)。
有没有更好的方法来实现相同的行为而不浪费数据?
答案 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)
})
}