可以将服务器端逻辑添加到 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 以实现自动增量密钥吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何以BLOB格式将图像上传到Firebase存储?

Firebase存储安全规则为特定用户提供访问权限

使用 multer 将图像上传到 Firebase 存储问题

为啥我不能以这种方式将数据添加到 Firebase?

将 APNS 证书添加到 Google Firebase

无法访问 Firestore 快照中的数据以将标记添加到存储在 Firebase 中的 Google 地图