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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.