如何使用firebase实时数据库ios增加特定节点中的值

Posted

技术标签:

【中文标题】如何使用firebase实时数据库ios增加特定节点中的值【英文标题】:How to increment the value in specific node with firebase realtime database ios 【发布时间】:2018-10-28 04:11:00 【问题描述】:

我正在使用聊天应用程序,我想维护接收方的未读计数。我在控制台中的 json 结构看起来像

user_history
|
|--> user_a_uuid
    |-> last_msg
    |-> last_msg_timestamp
    |-> unread_count

这个问题的范围是,如何增加unread_count 的值。在递增之前,我将user_a_uuid 和节点user_historyunread_count 作为常数。所以我尝试如下

dbRef.child("user_history")
     .child(user_a_uuid)
     .child("unread_count")
     .runTransactionBlock  (unreadCount) -> TransactionResult in 
        var value = unreadCount.value as? Int

        if value == nil 
            value = 0
        

        unreadCount.value = value! + 1
        return TransactionResult.success(withValue: unreadCount)

实际上,我从here 借用了这个解决方案。我也尝试关注doc。但问题是,我不想像在文档中那样在根节点上运行事务。我只想在unread_count 文档上运行事务。

我面临的问题:

在尝试此代码后,我面临的问题是,unread_count 节点被立即删除,而我在完成块内返回TransactionResult,它添加了unread_count。问题是由于unread_count 被删除,该值没有增加。它总是停留在1

提前致谢。

【问题讨论】:

请考虑发表评论,尚不清楚哪一部分。 【参考方案1】:

您似乎希望增加存储在节点中的计数器而不影响节点中的其他项目。根据问题中的信息,由于计数存储在代码中,因此在此用例中似乎不需要使用事务块。

在递增之前,我有 user_a_uuid 和节点 user_history & unread_count 为常量

我相信这意味着您将 unread_count 存储在代码中的 变量 中,因此如果这是正确的,它只需要在代码中递增并写入节点。

从重复结构开始:

user_history
   uid_0
      last_msg: "some message"
      last_msg_timestamp: "20181028075700"
      unread_count: 2

现在我们添加了另一条消息。 var 需要递增,然后 Firebase 中的相应节点需要使用新值进行更新。这是执行此操作的代码:

func updateMsgCount()  
   self.unread_count += 1 //this is a class var or however it's stored in code
   let unreadCountRef =  self.ref.child("user_history").child("uid_0").child("unread_count")
   unreadCountRef.setValue(self.unread_count)

但是,假设 unread_count 未存储在代码中,而仅存储在 Firebase 中。这是在 unread_count 节点中读取的代码,增加计数并将其存储回 Firebase。

func updateCount() 
   let unreadCountRef = self.ref.child("user_history").child("uid_0").child("unread_count")
   unreadCountRef.observeSingleEvent(of: .value, with:  snapshot in
      var currentCount = snapshot.value as? Int ?? 0
      currentCount += 1
      unreadCountRef.setValue(currentCount)
   )

如果你真的需要一个事务块,这里有一个来完成同样的事情

func updateCountTransactionStyle() 
    let unreadCountRef = self.ref.child("user_history").child("uid_0").child("unread_count")
    unreadCountRef.runTransactionBlock(  (currentData: MutableData) -> TransactionResult in

        var currentCount = currentData.value as? Int ?? 0
        currentCount += 1
        currentData.value = currentCount

        return TransactionResult.success(withValue: currentData)
    )

【讨论】:

感谢您的努力。实际上我没有在变量中维护unread_count,我只需要在接收方读取它并显示为徽章。原因是,这里使用的事务是用户可以从多个设备登录,虽然从多个设备同时发送消息是不切实际的,但我添加了这个以防发生此类事件。您分享的最后一个块实际上与我用较短版本提出的问题相同。 我在我的代码中发现了错误,其中设置了last_messagelast_msg_timestampunread_count 的整个字典。整个字典的这种写作删除了unread_count。解决方案是遍历字典allKeys中的每个键,并在节点上一一写入。 @RatulSharker 很高兴您发现了这个问题!我希望我的回答有所帮助,因为我认为这是您问题的解决方案,即使有一个单独的问题。如果它帮助或提供了方向,请接受它,以便它可以帮助他人。我不认为遍历节点是最好的解决方案。从我的两个示例中可以看出,您应该能够只读取 unread_count、递增并将其写回而不擦除其他值。 我必须遍历字典的情况,因为发送方设置此值,接收方意味着在接收方进入消息详细信息视图时将其设置为零。在您的建议中,last_messagelast_message_timestampunread_count 在将字典写入该节点之前需要先读取。这似乎是更多的任务,读写unread_count 可能会在发送方递增它而接收方将其设置为零时产生错误,因此不能让递增操作在事务之外进行。

以上是关于如何使用firebase实时数据库ios增加特定节点中的值的主要内容,如果未能解决你的问题,请参考以下文章

将新数据添加到特定子项时如何使用 Cloud Functions 将数据写入 Firebase 实时数据库

如何从 firebase 实时数据库中获取数据并更改一个文本字段以表示该特定记录?

如何从 Firebase 实时数据库中检索特定数据?

Firebase 实时数据库:如何监听节点的特定项目子集?

Firebase 实时数据库:如何在按值排序后围绕特定键检索 10 条记录?

如何在 Firebase 实时数据库(Android 开发)中获取特定子项的键值?