googleapis / googleapis/google-cloud-node

FieldValue.increment() is not working as expected on subfields of a map

Open
#7,457 3 comments 0 reactions 1 assignee Claimed by @MarkDuckworth View on GitHub
api: firestore library: nodejs-firestore priority: p2 type: bug
Dominant language
TypeScript
Stars
3.2k
Forks
712
Avg merge
2d 3h
Merged PRs (30d)
99

Description

Thanks for stopping by to let us know something could be better!

**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.

1) Is this a client library issue or a product issue?
I think it's probably something that should be at-least handled by this library.

2) Did someone already solve this?
- Search the issues already opened: https://github.com/googleapis/nodejs-firestore/issues ✅
- Search the issues on our "catch-all" repository: https://github.com/googleapis/google-cloud-node ✅
- Search or ask on StackOverflow (engineers monitor these tags): http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js ✅

3) Do you have a support contract?
Nope

If the support paths suggested above still do not result in a resolution, please provide the following details.

#### Environment details

- OS: Mac
- Node.js version: 18.16.0
- npm version: 9.5.1
- `@google-cloud/firestore` version: ^6.8.0

#### Steps to reproduce

The `FieldValue.increment()` function does not work as expected on subFields of a map value. Given this data structure of the object in the database:

```ts
{
amount: 1,
map: {
amount: 1
}
}
```

If I run this code:

```ts
await docRef.update({
amount: FieldValue.increment(2),
sub: {
amount: FieldValue.increment(2)
}
})
```

The data in the database ends up being:

```ts
{
amount: 3,
map: {
amount: 2
}
}
```

It would seem that incrementing using this object syntax does increment on top-level keys, but "sets" the value of subfields of maps to the exact increment value, rather than incrementing.

To me this feels like the incorrect behaviour - I would firstly expect that `map.amount` would be `3`, OR expect the SDK to throw an error as it does when using `FieldValue.delete()` on a subfield of a map in this way.

The "workaround" is to use dot-notation strings as keys on the top level of the object like so:

```ts
await docRef.update({
amount: FieldValue.increment(2),
'sub.amount': FieldValue.increment(2)
})
```

This does work as expected and the data in the db ends up being:

```{
amount: 3,
map: {
amount: 3
}
}
```

This issue has been observed in SO here:
https://stackoverflow.com/questions/56427582/how-to-use-fieldvalue-increment-on-the-property-of-an-object-type-document-fie

It feels like this warrants an issue and a change to how the sdk handles this to bring it in line with how it handles `FieldValue.delete()` on subfields of a map where for example, this code throws an error:

```ts
await docRef.update({
amount: FieldValue.increment(2),
sub: {
amount: FieldValue.delete()
}
})
```

Error:

> Update() requires either a single JavaScript object or an alternating list of field/value pairs that can be followed by an optional precondition. Value for argument "dataOrField" is not a valid Firestore value. FieldValue.delete() must appear at the top-level and can only be used in update() or set() with {merge:true} (found in field "sub.amount")

It took a wilte to figure out what was going on here, and can be especially confusing when incrementing from `0` because it _seems_ like the first request works, but then subsequent requests do not behave as expected. Eg:

Db is:
```ts
{
amount: 0,
map: {
amount: 0
}
}
```

Run:

```ts
await docRef.update({
amount: FieldValue.increment(1),
sub: {
amount: FieldValue.increment(1)
}
})
```

Db is now:
```
{
amount: 1,
map: {
amount: 1
}
}
```

Which seems like it works... But if you run the exact same code again:

```ts
await docRef.update({
amount: FieldValue.increment(1),
sub: {
amount: FieldValue.increment(1)
}
})
```

Now the data in the db ends up being incorrect:
```
{
amount: 2,
map: {
amount: 1
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.