更新firestore文档中嵌套对象中的字段?

时间:2018-03-07 11:34:45

标签: javascript firebase google-cloud-firestore

我的数据结构如下:

enter image description here

我想编辑“first”对象中“test”键的值。我按照https://firebase.google.com/docs/firestore/manage-data/add-data

上的文件进行了操作

但它对我不起作用。

nodejs代码:

var setAda = dbFirestore.collection('users').doc('alovelace').update({
        first : {
            test: "12345"
            }
});

firestore中的结果: enter image description here

“test2”键消失了。但是,我只想更新“test”的值并保留“test2”。

针对此问题的任何解决方案?

9 个答案:

答案 0 :(得分:7)

根据您提供的链接,它说:

  

如果您的文档包含嵌套对象,则可以使用"点符号"在调用update()时引用文档中的嵌套字段:

因此,您需要使用dot notation才能更新一个字段而不会覆盖,所以像这样:

var setAda = dbFirestore.collection('users').doc('alovelace').update({
    "first.test": "12345"
});

然后你会:

 first
  test: "12345"
  test2: "abcd"

答案 1 :(得分:1)

试试这个: 它有效吗?

var setAda = dbFirestore.collection('users').doc('alovelace').update({
        "first.test" : "12345"
});

答案 2 :(得分:1)

万一有人使用 TypeScript (例如在Cloud函数中),下面的代码将使用点符号更新嵌套字段。

var setAda = dbFirestore.collection('users').doc('alovelace').update({
    `first.${variableIfNedded}.test`: "12345"
});

答案 3 :(得分:0)

Peter的解决方案很棒,但不适用于动态密钥。这段代码要好得多:

var nestedkey = 'test';
var setAda = dbFirestore.collection('users').doc('alovelace').update({
    [`first.${nestedkey}`]: "12345"
});

答案 4 :(得分:0)

对于那些需要更通用和递归的用户而言,这是一个使用Typeial Partial进行无损更新Foo Firestore文档的功能:

private objectToDotNotation(obj: Partial<Foo>, parent = [], keyValue = {}) {
    for (let key in obj) {
        let keyPath = [...parent, key];
        if (obj[key]!== null && typeof obj[key] === 'object')
            Object.assign(keyValue, this.objectToDotNotation(obj[key], keyPath, keyValue));
        else
            keyValue[keyPath.join('.')] = obj[key];
    }
    return keyValue;
}

public update(foo: Partial<Foo>) {
    dbFirestore.collection('foos').doc('fooId').update(
        this.objectToDotNotation(foo)
    )
}

答案 5 :(得分:0)

如果您不希望在“第一个”字段不存在的情况下发生异常,请尝试将set{merge: true}选项一起使用,而不要使用update

var setAda = dbFirestore.collection('users').doc('alovelace').set({
        first : {
            test: "12345"
        }
}, {merge: true});

答案 6 :(得分:0)

对于Swift 4

let dictionary:[String:Any] = ["first.test" : "12345"]
let plansDocumentReference = Firestore.firestore().collection("users").document("alovelace")              
plansDocumentReference.updateData(dictionary) { err in
                if let err = err {
                    print("Error updating document: \(err)")

                }}

您可以通过将记录添加到字典中来更新多个字段,也可以通过使用字符串变量替换字典中的固定文本来构建基于变量的子键。

该技术还可以通过使用字典作为任何键的值来替换文档中的整个单个键子块

答案 7 :(得分:0)

我正在寻找没有多余参数的打字稿版本,请牢记键入完成...最后得到以下内容:

TS Playground example

function objectToDotNotation(obj: any): any {

    return Object.keys(obj).reduce( (dnObj, key) => {
        const value = obj[key];

        if (value !== null && typeof value === 'object') {            
            const childObj = objectToDotNotation(value);

            Object.keys(childObj).forEach( childKey => {
                dnObj = {...dnObj, [`${key}.${childKey}`]: childObj[childKey] };
            });
        } else {            
            dnObj = {...dnObj, [key]: value };
        }

        return dnObj;
    }, {});
}

答案 8 :(得分:0)

使用 set 函数并在选项中传递 merge: true 以更新深度嵌套的字段而不覆盖其他字段。

const firstore = firebase.firestore()
const ref = firestore.doc('users/alovelace').set({
  first : {
    test: "12345"
  }
}, { merge: true })

使用这种方法,即使字段埋藏 20 层深,您也可以更新它。