Reputation: 936
I have a data structure like:
I want to edit the value of "test" key in "first" object. I followed the document on https://firebase.google.com/docs/firestore/manage-data/add-data
But it did not work for me.
The nodejs code:
var setAda = dbFirestore.collection('users').doc('alovelace').update({
first : {
test: "12345"
}
});
The "test2" key was gone. However, I only want to update the value of "test" and keep the "test2".
Any solution for this problem?
Upvotes: 49
Views: 25725
Reputation: 918
If you don't want an exception that occur if 'first' field doesn't exist, try using set
with {merge: true}
option instead of update
.
var setAda = dbFirestore.collection('users').doc('alovelace').set({
first : {
test: "12345"
}
}, {merge: true});
Edit:
Thanks to @Shane Walker, the latest version(9.8.1) of Firestore has been changed so that update
works the same as set
with {merge: true}
option.
Firebase JavaScript SDK Release Notes
Upvotes: 12
Reputation: 468
Peter's solution's great, but it's not works with dynamic key. Following code can works with it:
var nestedkey = 'test';
var setAda = dbFirestore.collection('users').doc('alovelace').update({
[`first.${nestedkey}`]: "12345"
});
Upvotes: 34
Reputation: 124
Use the set
function and passing merge: true
in options to update deeply nested fields without overwriting other fields.
const firstore = firebase.firestore()
const ref = firestore.doc('users/alovelace').set({
first : {
test: "12345"
}
}, { merge: true })
With this method, you can update a field even if it's buried 20 levels deep.
Upvotes: 1
Reputation: 1
I was looking for a version in typescript without the extra params, having type completion in mind... Ended up with the following:
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;
}, {});
}
Upvotes: 0
Reputation: 1
For 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)")
}}
You can update multiple fields by adding records to the dictionary as well as build variable based sub-keys by replacing the fixed text in the dictionary with string variable.
This technique also works to replace entire single key sub-blocks in the document by using a dictionary as the value for any key
Upvotes: 0
Reputation: 1985
For those who need something more generic and recursive, here is a function that updates a Foo Firestore document non destructively with a typescript Partial :
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)
)
}
Upvotes: 1
Reputation: 3248
In case somebody is using TypeScript (like in Cloud functions for example) here is the code to update nested fields with dot notation.
var setAda = dbFirestore.collection('users').doc('alovelace').update({
`first.${variableIfNedded}.test`: "12345"
});
Upvotes: 9
Reputation: 61
Try this one: Does it work like that?
var setAda = dbFirestore.collection('users').doc('alovelace').update({
"first.test" : "12345"
});
Upvotes: 1
Reputation: 80952
According to the link you provided, it says this:
If your document contains nested objects, you can use "dot notation" to reference nested fields within the document when you call update():
Therefore you need to use dot notation
to be able to update only one field without overwriting, so like this:
var setAda = dbFirestore.collection('users').doc('alovelace').update({
"first.test": "12345"
});
then you will have:
first
test: "12345"
test2: "abcd"
Upvotes: 69