6

I have a Firebase Firestore database, in which I have a collection users. There is an array in the collection and in the array there is a map. In the map, there is a field qty. I want to increment that qty field value.

Using increment doesnt help as the qty is inside an array index

db.collection("users").doc(checkId).update({
    myCart: firebase.firestore.FieldValue.arrayUnion({
        qty: firebase.firestore.FieldValue.increment(1),
    }),
});

and this results to the following error:

Uncaught (in promise) FirebaseError: Function FieldValue.arrayUnion() called with invalid data. FieldValue.increment() can only be used with update() and set()

Christos Lytras
  • 36,310
  • 4
  • 80
  • 113

4 Answers4

8

My answer below won't work, given that the qty is in an array. The only way to update an item in an array is to read the entire document, update the item in the array, and then write the entire array with the updated item back to the document.


An alternative would be to use a map instead of an array, and then update the qty using the approach outlined in my (old, and non-working) answer below

You need to specify the full path to the field you're trying to update. So I think in your case, that'll be:

db.collection("users").doc(checkId).update({
  "myCart.0.qty": firebase.firestore.FieldValue.increment(1)
}),
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
6

The field you want to update is embedded in an array. In this case, you can't use FieldValue.increment(), since it's not possible to call out an array element as a named field value.

What you'll have to do instead is read the entire document, modify the field in memory to contain what you want, and update the field back into the document. Also consider using a transaction for this if you need to update to be atomic.

(If the field wasn't part of an array, you could use FieldValue.increment().)

luckyhandler
  • 10,651
  • 3
  • 47
  • 64
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
2

As of today (29-04-2020)... this is tested by me.

Suppose my data structure is like this:

collection: Users Any document: say jdfhjksdhfw It has a map like below map name: UserPageVisits map fields: field1,field2,field3 etc

Now we can increment the number field in the map like below:

mapname.field1 etc...

That is use the dot operator to access the fields inside the map just like you would do to an object of javascript.

JAVA Code (Android), update the field using transactions so they can complete atomically.

transaction.update(<documentreference object>,"UserPageVisits.field1",FieldValue.increment(1));

I have just pushed a version of my app which uses this concept and it's working.

Kudos !!

My Best Regards

Coder Marine
  • 73
  • 10
  • Thanks! This worked with the Flutter SDK and means I don't have to read the value first, increment and then write. I can just increment directly. Saved me a bunch of reconfiguration work, this should be the accepted answer! – Marvioso Oct 14 '20 at 19:40
  • Glad it helped you. :-) – Coder Marine Jan 05 '21 at 07:25
-1

Previous answers helped me as well, but dont forget about the "merge" property!!! Otherwise it will overwrite your entire array, losing other fields.

var myIndex = 0;
const userRef = db.collection('users').doc(checkId);
return userRef.update({
      'myCart.${myIndex}.qty': admin.firestore.FieldValue.increment(1)
    }, {
        merge: true
    });
Alex Balas
  • 99
  • 1
  • 1
  • The `.update()` method has no `{ merge: true }` option. I believe you are thinking about `.set(data, { merge: true})` – Frenchcooc Oct 04 '21 at 21:24