【问题标题】:Cloud Firestore: Update fields in nested objects with dynamic keyCloud Firestore:使用动态键更新嵌套对象中的字段
【发布时间】:2018-04-27 23:27:47
【问题描述】:

按照firestore的官方文档:

{
    name: "Frank",
    favorites: { food: "Pizza", color: "Blue", subject: "recess" },
    age: 12
}

// To update favorite color:
db.collection("users").doc("frank").update({
    "favorites.color": "Red"
})

我想使用动态键而不是颜色。

db.collection("users").doc("frank").update({
    "favorites[" + KEY + "].color": true
});

这当然是不可能的,会报错。

我一直在尝试这样做:

db.collection("users").doc("frank").update({
    favorites: {
        [key]: {
            color": true
        }
    }
});

它实际上是用正确的键更新,但不幸的是,它覆盖了其他键(它们正在被删除)。

【问题讨论】:

    标签: javascript firebase google-cloud-firestore


    【解决方案1】:

    我发现该解决方案的灵感来自 firebase 解决方案(将“/”替换为“.”)。

    var usersUpdate = {};
    usersUpdate[`favorites.${key}.color`] = true;
    
    db.collection("users").doc("frank").update(usersUpdate);
    

    【讨论】:

    • 我想知道这是否真的有效。我希望它会用具有单个值的新值覆盖usersUpdate 的当前值,即{favorites {KEY: {color: true}}}。如果您说的是正确的,那么将无法实际将usersUpdate 更新为全新的价值。
    • 更简单地说,@Georg Hackenberg 指出了这个解决方案:db.collection('users').doc('frank').update({ [`favorites.${key}.color`] = true })
    • 为什么无效?您可以在 es6 中使用反引号。该解决方案仍然有效,它与下面的答案非常相似。 developers.google.com/web/updates/2015/01/ES6-Template-Strings
    • 这个解决方案是错误的,因为这会创建一个新的字段 usersUpdate 类型为 map 和子收藏夹。${key}.color : true - 如果 key=1234 那么 usersUpdate 字段看起来像usersUpdate { favorites.1234.color : true }
    【解决方案2】:

    这个解决方案对我有用:

    db.collection('users').doc('frank').update({
      [`favorites.${key}.color`]: true
    });
    

    【讨论】:

    • 正确的解决方案。
    • db.collection('users').doc('frank').update({ [` favorites.${key}.color `]: true })
    • 这个解决方案是正确的。另一种解决方案:db.collection('users').doc('frank').update({ [`favorites.${key}.color `]: true }) 并且还要小​​心避免 [``] 部分内的空格,即如果包含空格db.collection('users').doc('frank').update({ [` favorites.${key}.color `]: true },您最终会做错
    • 虽然没有做任何嵌套的东西:/只是更新
    • 潜伏者注意:这适用于更新,但对于设置它保存为名称中带有点的单个道具,而不是嵌套属性。
    【解决方案3】:

    您可以更新变量(ly)命名嵌套对象的特定字段,如下所示。

    ref.set({
        name: "Frank",
        favorites: { food: "Pizza", quantity: 2 }
    });
    
    //now the relevant update code
    var name = "favorites";
    var qty = 111;
    var update = {};
    update[name+".quantity"] = qty;
    ref.update(update);
    

    https://jsbin.com/hihifedizu/edit?js,console

    【讨论】:

    • 这是一般用途最有用的答案。感谢您帮助我。
    【解决方案4】:

    请注意一个潜在的陷阱:在发现可以使用点语法更新嵌套字段后,我尝试以同样的方式使用set(),因为无论对象是否已经存在,我都需要它来工作:

    var updateObj = {['some.nested.property']: 9000};
    docRef.set(updateOb, {merge: true});
    

    不幸的是,这不起作用——它设置了一个键为some.nested.property 的属性。不一致,但没关系。

    幸运的是,set(updateObj, {merge: true}) 似乎进行了深度合并,因此如果您将更新对象构造为完全嵌套的对象,您的嵌套对象也将被正确合并:

    // create the object
    db.doc('testCollection/doc').set({p1: {['p2']: {p3: true}}}, {merge: true})
    // update the existing object
    db.doc('testCollection/doc').set({p1: {['p2']: {p4: true}}}, {merge: true})
    
    // result is now this:
    { p1: { p2: { p4: true, p3: true } } }
    

    【讨论】:

    • 笏。他们什么时候在那个忍者?我敢肯定它并不总是这样。它曾经做过浅合并 IIRC。但是,嘿,它非常有用,所以感谢您写下它! ??
    • 你让我很开心,我很长一段时间都遇到同样的问题?
    • 哇。我不知道这行得通。很不错。希望它被记录在某个地方。
    【解决方案5】:

    我觉得这是上述所有方法中最简单的解决方案:)

    db.collection("users").doc("frank").update({
        [`favorites.${KEY}.color`]: true
    });

    【讨论】:

      猜你喜欢
      • 2018-11-12
      • 1970-01-01
      • 2019-02-13
      • 2021-04-14
      • 2021-02-02
      • 2018-08-15
      • 2021-12-15
      • 2019-03-31
      相关资源
      最近更新 更多