97

following the official documentation of 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" }) 

I would like to use a dynamic key instead of color.

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

this is of course not possible and will throw an error.

I've been trying to do this :

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

It is actually updating with the right key but unfortunately, it is overwriting the other keys (they are being deleted).

7 Answers 7

118

I found the solution inspired by a firebase solution (replacing "/" by ".").

var usersUpdate = {}; usersUpdate[`favorites.${key}.color`] = true; db.collection("users").doc("frank").update(usersUpdate); 
Sign up to request clarification or add additional context in comments.

8 Comments

I'm wondering if that actually works. I would expect it to overwrite the current value of usersUpdate with the new one with a single value, namely {favorites {KEY: {color: true}}}.If what you say is correct, then there would be no way to actually update usersUpdate to a completely new value.
more briefly, @Georg Hackenberg points out this solution: db.collection('users').doc('frank').update({ [`favorites.${key}.color`] = true })
Why is it invalid? You can use backticks in es6. This solution still work, it is really similar to the answer below. developers.google.com/web/updates/2015/01/ES6-Template-Strings
This solution is wrong as this will create a new field usersUpdate of type map with child favorites.${key}.color : true - if key=1234 then usersUpdate field will look like usersUpdate { favorites.1234.color : true }
|
77

This solution worked for me:

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

6 Comments

Correct solution.
db.collection('users').doc('frank').update({ [` favorites.${key}.color `]: true })
This solution is correct. Also alternate solution : db.collection('users').doc('frank').update({ [`favorites.${key}.color `]: true }) and also be careful enough to avoid blank spaces inside [``] section i.e you would end up doing wrong if you include blank space db.collection('users').doc('frank').update({ [` favorites.${key}.color `]: true }
doesn't make any nested stuff though :/ just update
Note for lurkers: This works for update, but for set it saves as a single prop with dot in it's name, not as a nested property.
|
35

Just a note about a potential pitfall: After discovering that you can update nested fields using a dot syntax, I tried using set() the same way, since I needed it to work whether the object already exists or not:

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

Unfortunately, this doesn't work – it sets a property whose key is some.nested.property instead. Inconsistent, but okay.

Fortunately, it appears that set(updateObj, {merge: true}) does a deep merge, so if you construct your update object as a fully nested object, your nested objects will also be properly merged:

// 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 } } } 

4 Comments

Wat. When did they ninja in that? I'm sure it wasn't always like that. It used to do a shallow merge IIRC. But hey, it extremely useful, so thanks for writing about it! 👍🏻
You made my day man, I was having the same issue for a long time 🥰
Wow. I had no clue this worked. Very nice. Wish it was documented somewhere.
Thanks undefined, you defined everything needed for this
3

You can update specific fields of variable(ly) named nested objects like below.

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

1 Comment

This is the most useful answer for general use. Thanks for helping me out.
2

2022 Update with Webversion 9 (modular):

const docRef = doc(db, 'users', frank); var usersUpdate = {}; usersUpdate[`favorites.${key}.color`] = true; updateDoc(docRef, userUpdate); 

1 Comment

this is the modern answer guys
0

you can use

var auxKey = "history." + someVar; var dataToUpdate = { [auxKey]: "new data generated" }; db.collection("users").doc("frank").update(dataToUpdate); 

1 Comment

result: {"history": {"valueOfSomeVar": "new data generated"}}
-1

I felt this is the simplest solutions of all the above :)

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.