【问题标题】:Firebase fanout data to update specific fields remove other siblings fieldsFirebase 扇出数据以更新特定字段删除其他同级字段
【发布时间】:2016-11-24 06:24:16
【问题描述】:

每个用户都有一个对话节点,每次新对话有新消息时,我都需要为对话中涉及的两个用户更新两个对话节点,我只想在此处更新“lastMessage”和“tinestamp”字段是我的尝试:

let fanoutObject = [userPath      : dataToUpdate,
                    otherUserPath : dataToUpdate]

K.FirebaseRef.root.updateChildValues(fanoutObject)

每个用户的路径在哪里:

"/users/{userID}/conversations/{conversationID}"

和dataToUpdate:

let dataToUpdate:[String:AnyObject] = ["timestamp"  : message.timestamp,
                                       "lastMessage": message.textBody]

结果:

更新每个用户的节点对话删除对话节点中的其他字段!

每个用户的对话节点是:

  "conversations" : {
    "{conversationID}" : {
      "lastMessage" : "your name ?",
      "seen" : true,
      "timestamp" : 1467849600000,
      "with" : {
        "country" : "US",
        "firstName" : "John",
        "profileImage" : "https://..."
      }
    }
  }

请注意,节点 conversations 位于节点 user 内,该节点是根节点 users 内的一个元素

更新后是:

  "conversations" : {
    "{conversationID}" : {
      "lastMessage" : "your name ?",
      "timestamp" : 1467849600000,
    }
  }

但我只是希望更新这两个值并保留其他值?

根据文档,我的代码应该可以工作:

updateChildValues 更新定义路径的一些键 替换所有数据。

【问题讨论】:

    标签: ios json swift firebase firebase-realtime-database


    【解决方案1】:

    解析您的代码有点困难,但很可能是 updateChildValues() 的行为让您感到困惑。

    当您调用updateChildValues() 时,Firebase 服务器将遍历您传入的对象。对于其中的每条路径,它将将该路径中的整个值替换为您传入的值。

    所以如果你当前的 JSON 是:

    {
      "Users": {
        "uidForUser1": {
          "name": "iOSGeek",
          "id": 2305342
        },
        "uidForUser2": {
          "name": "Frank van Puffelen",
          "id": 209103
        }
    }
    

    更新是(JSON 格式,Firebase 数据库的通用语):

    {
      "users/uidForUser2/name": "puf",
      "users/uidForUser1/name": "My actual name"
    }
    

    您生成的 JSON 将是:

    {
      "Users": {
        "uidForUser1": {
          "name": "My actual name",
          "id": 2305342
        },
        "uidForUser2": {
          "name": "puf",
          "id": 209103
        }
    }
    

    但如果你发送以下更新:

    {
      "users/uidForUser1": {
        "name": "My actual name"
      },
      "users/uidForUser2": {
        "name": "puf"
      }
    }
    

    生成的 JSON 将是:

    {
      "Users": {
        "uidForUser1": {
          "name": "My actual name"
        },
        "uidForUser2": {
          "name": "puf"
        }
    }
    

    更新

    更新同一对象中的两个字段,但不修改其他字段:

    {
      "path/to/object/field1": "new value",
      "path/to/object/field2": "new value2"
    }
    

    【讨论】:

    • 感谢您的回答,这是有道理的,但是有没有办法在节点中使用相同的更新更新两个字段而不删除其他兄弟字段,假设我想同时更新名称和 ID我们假设还有其他字段,例如年龄,如何使用相同的调用更新 id 和 name ?
    • 我也添加了一个例子。
    • 谢谢,但很遗憾,我们不能只将字典传递给根对象并告诉它只替换字典中存在的子字段的值而保持其他兄弟字段不变.因为使用您的方法我需要为每个字段生成一个路径,如果我将有 5 个用户和 3 个字段 = 15 个路径来生成...
    • 对于刚接触多位置更新的开发人员来说,这确实是一个常见的困惑来源。它以这种方式工作的原因是我们必须保持 API 与之前的实现向后兼容。根据我的经验,生成路径很简单,但是这引起的混乱确实很不幸。
    • @FrankvanPuffelen,官方文档对我来说确实不准确。关于如何正确使用 updateChildValues 设置多个值,同时不影响其他值的简单更改措辞或示例(例如此处提供),将为许多人节省大量时间! (也许还有数据!)
    【解决方案2】:

    或者,您可以通过提供完整路径替换旧值来更新 lastMessagetimeStamp 数据:

    let lastMessagePath = "/users/{userID}/conversations/{conversationID}/lastMessage"
    let lastTimeStampPath = "/users/{userID}/conversations/{conversationID}/timestamp"
    
    K.FirebaseRef.child(lastMessagePath).setValue(message.timestamp)
    K.FirebaseRef.child(lastTimeStampPath).setValue(message.textBody)
    

    【讨论】:

    • 谢谢,但我认为有针对特定节点的批量更新,因为使用您的方法我将不得不更新 4 个节点,如果我将为 5 个用户更新 3 个字段,我将拥有创建 15 个参考...
    • 根据Docs,它应该可以工作,但它会更新值并删除兄弟字段,它被视为setValue而不是更新!
    • 我正在努力解决这种不一致的行为。 db.ref('myPathToObject').update({prop1: '...'}) 按预期更新对象。然而这:const updates = {} updates['myPathToObject'] = {prop1: '...'} db.ref().update(updates) 完全覆盖了对象。有没有一种方法可以实现扇出,而不必分别为每个属性编写更新?
    猜你喜欢
    • 2017-11-30
    • 2020-07-19
    • 2012-05-11
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-12
    相关资源
    最近更新 更多