可以将服务器端逻辑添加到 firebase 以实现自动增量密钥吗?
Posted
技术标签:
【中文标题】可以将服务器端逻辑添加到 firebase 以实现自动增量密钥吗?【英文标题】:Can server side logic be added to firebase to implement an automatically incremental key? 【发布时间】:2015-10-14 17:57:30 【问题描述】:我是 firebase 新手,我正在尝试实现一个 ios 聊天应用程序。我想知道是否有办法在收到的消息中添加增量 id。
例如: 我将以下消息发送到 firebase
date: "2015-10-14T04:30:43", name: "Jacob" text:"Hi" userId: "y8jFdNwRAX"
firebase 是否有可能向其添加 messageId 键
msgId:1, date: "2015-10-14T04:30:43", name: "Jacob" text:"Hi" userId: "y8jFdNwRAX";
如果我发送另一个 msg,firebase 添加 msgId 并将其增加 1:
msgId:2, date: "2015-10-14T04:31:40", name: "Jacob" text:"morning" userId: "y8jFdNwRAX";
不确定 firebase 是否可以做到这一点?任何帮助表示赞赏。提前谢谢你。
【问题讨论】:
答案有点像。但是,msgId 的作用是什么?如果您正在进行某种订购,则可以使用日期戳。您还可以通过在子节点中存储一个值来实现代码增量(大约有 100 种方法可以做到这一点)。甚至是一个单独的节点来存储值,并且可以在您添加帖子时递增。 @FrankvanPuffelen 服务器端逻辑? 不。但是做这样的增量是一个坏主意,不管你是在客户端还是服务器端。push()
存在是有原因的,原因在文档中进行了解释。
@Jay 你的评论更有帮助。如果你把它变成一个答案,它会得到我的支持。
@FrankvanPuffelen,我是 firebase 新手,不确定您是否可以在 firebase 中执行服务器端逻辑。你说“是的,它可以”,你真的是这个意思吗?或者只是随机指向 firebase.com/docs/ios?
【参考方案1】:
所以这个问题的答案是否定的,它不会发生在某种自动化的服务器端逻辑中。而且,这通常是个坏主意。
有很多方法可以模拟计数器,但使用起来确实很棘手,而且有很多方法可能出错,这不是好的代码。
所以我建议寻找另一种解决方案:
也许每条消息都有一个子节点来跟踪它是否被读取?
message_id_1
timestamp: "2015-10-14T04:30:43"
name: "Jacob"
text: "Hi"
userId: "y8jFdNwRAX"
read: "yes"
message_id_2
timestamp: "2015-10-14T04:30:50"
name: "Bob"
text: "Hi Back At Ya"
userId: "y9jaksjk"
read: "no"
您甚至可以有一个“已读”节点和一个“未读”节点
read_messages
message_id_1
timestamp: "2015-10-14T04:30:43"
name: "Jacob"
text: "Hi"
userId: "y8jFdNwRAX"
unread_messages
message_id_2
timestamp: "2015-10-14T04:30:50"
name: "Bob"
text: "Hi Back At Ya"
userId: "y9jaksjk"
这是一个棘手的问题:将消息存储在他们自己的节点中,并在用户节点中引用那些未读的消息
all_messages
message_id_1
timestamp: "2015-10-14T04:30:43"
from_userId: "y9jaksjk"
text: "This is message 1"
message_id_2
timestamp: "2015-10-14T04:30:50"
from_userId: "y9jaksjk"
text: "this is message 2"
users
"y8jFdNwRAX"
my_unread_messages:
message_id_1: true
(message_id_1: true 保存为用户的子项是一个引用,表示该消息是给该用户的,并且尚未被阅读。阅读时,删除引用。)
所有这些都是推测,因为我们不知道应用程序的范围和消息的使用。
您可能需要更多地访问文档并查看为其他选项提供的一些示例代码。
【讨论】:
非常感谢@Jay。我正在考虑在消息中添加“阅读”键,但如果这是群聊,则需要多个消息副本。所以这就是为什么我更喜欢有序的消息 ID。我可以假设在 Firebase 中实现服务器逻辑是不可能的吗?因为到目前为止我还没有找到这样的例子。 这通常是正确的。即使它可用,所提出的其他方法也可能是更好的解决方案。虽然您可以制作消息的多个副本(数据重复在 firebase 中是 A-OK),但您可能需要考虑其他解决方案:可能是用户节点内的“unread_messages”子节点,其中包含用户尚未阅读的消息的引用。读取后,从节点中删除 message_id - 类似于上面的最后一个示例。 我不会说答案是否定的。事实上,它可以通过安全规则在客户端完成:jsfiddle.net/firebase/xLq7grcc 这仍然不是最好的计划,通常会解决错误的问题。 Push ID 通常是更好的选择。【参考方案2】:如果有人有同样的问题。我在服务器端使用时间戳作为“messageId”来跟踪订单(可能不是一个好主意,但它解决了我的需要),您可以在安全规则中的这个“messageId”上创建“.indexon”来获取更好的性能。
以下是安全规则的示例:
"rules":
"Messages":
"$Message":
".indexOn": "messageId"
iOS 中的设置代码:
msg[@"messageId"] = kFirebaseServerValueTimestamp;
注意,Firebase 可能存在一个错误:您从 FEventTypeChildAdded 收到的时间戳有时与保存在 Firebase DB 中的时间戳不同(相差几百毫秒)。
【讨论】:
【参考方案3】:我因为另一个原因遇到了同样的问题
增量键可以通过事务来实现: https://www.firebase.com/docs/ios/api/#firebase_runTransactionBlock
一个快速的例子:
let messagesRef = ...
let counterRef = ... //you need to keep the count of messages
counterRef.runTransactionBlock( (currentData) -> FTransactionResult! in
var value = currentData.value as? Int
if (value == nil) value=0
currentData.value = value! + 1
return FTransactionResult.successWithValue(currentData)
) (error, commited, snap) -> Void in
if error != nil
print(error)
if commited
//if increment is made set message
let messageInfo = ....
messagesRef.childByAppendingPath(snap.value).setValue(messageInfo)
如果唯一的目标是排序,那么 childbyautoid 函数就足够了,因为它会相应地创建键
messagesRef.childByAutoId().setValue(messageInfo)
希望这对某人有所帮助
【讨论】:
以上是关于可以将服务器端逻辑添加到 firebase 以实现自动增量密钥吗?的主要内容,如果未能解决你的问题,请参考以下文章