Reputation: 1723
So based on the firestore documentation on object fields:
// Create an initial document to update.
var frankDocRef = db.collection("users").doc("frank");
frankDocRef.set({
name: "Frank",
favorites: { food: "Pizza", color: "Blue", subject: "recess" },
age: 12
});
// To update age and favorite color:
db.collection("users").doc("frank").update({
"age": 13,
"favorites.color": "Red"
})
.then(function() {
console.log("Document successfully updated!");
});
How can I update multiple properties of the favorites field eg.
db.collection("users").doc("frank").update({
"age": 13,
"favorites.color": "Red",
"favorites.food": "Burger"
})
This FAILS with a msg in the console:
Unhandled error Error: Argument "dataOrField" is not a valid UpdateMap. Field "favorites" was specified multiple times.
I have also tried with the merge: true
option eg.
db.collection("users").doc("frank").update({
"age": 13,
"favorites": {
"color": "Red",
"food": "Burger"
}
}, {merge: true})
But this overwrites the entire favorites field, meaning 'subject' property is gone.
Any ideas?
Here is my actual code:
"cardId" comes from body.cardId on a POST request
return db.runTransaction(t => {
let user
let hasDefault = false
return t.get(userRef).then(userDoc => {
if (!userDoc.exists) throw new HttpsError('not-found', 'user-not-found')
user = userDoc.data()
if (!user.cards || !user.cards[cardId]) throw new HttpsError('not-found', 'card-not-found')
return updateCustomer(user.cid, { defaultCard: cardId })
}).then(customer => {
const prevDefaultId = Object.keys(user.cards).find(cardId => user.cards[cardId] && user.cards[cardId].default)
let userUpdateData = {}
if (prevDefaultId && prevDefaultId !== cardId) {
userUpdateData[`cards.${prevDefaultId}.default`] = false
}
userUpdateData[`cards.${cardId}.default`] = true
return t.update(userRef, userUpdateData, {merge: true})
})
})
I have worked around it by updating twice:
return db.runTransaction(t => {
let user
let hasDefault = false
return t.get(userRef).then(userDoc => {
if (!userDoc.exists) throw new HttpsError('not-found', 'user-not-found')
user = userDoc.data()
if (!user.cards || !user.cards[cardId]) throw new HttpsError('not-found', 'card-not-found')
return updateCustomer(user.cid, { defaultCard: cardId })
}).then(customer => {
const prevDefaultId = Object.keys(user.cards).find(cardId => user.cards[cardId] && user.cards[cardId].default)
if (prevDefaultId && prevDefaultId !== cardId) {
t.update(userRef, {
[`cards.${prevDefaultId}.default`]: false
}, {merge: true})
}
return t.update(userRef, {
[`cards.${cardId}.default`]: true
}, {merge: true})
})
})
Upvotes: 3
Views: 2927
Reputation: 17854
In order to update multiple fields in a Firestore document you need to use the field, value, field, value... format:
db.collection("users").doc("frank").update({
"age", 13, // field, value
"color, "red" // field, value
})
If you want to update a nested field, you have a couple options.
Use the dot notation like you mentioned:
db.collection("users").doc("frank").update({
"age", 13,
"favorites.color", "Red",
"favorites.food", "Burger"
})
Make your "value" a map:
db.collection("users").doc("frank").update({
"age", 13,
"favorites", mapOf(
"color" to "Red",
"food" to "Burger"
})
Upvotes: 3