Angularfire: Firestore document .update() not working as intended

Created on 10 Oct 2017  路  8Comments  路  Source: angular/angularfire

Version info

Angular: 4.3

Firebase: 4.5.0

AngularFire: 5.0 rc1

Other (e.g. Ionic/Cordova, Node, browser, operating system):

How to reproduce these conditions

https://stackblitz.com/edit/angular-abcgfq?file=app%2Fapp.component.ts

I think stackblitz is having trouble with the AngularFire2 import, if you get the red squiggly under angularfire2/firestore go to dependencies, delete the library and re-install

Steps to set up and reproduce

Create an AngularFirestoreDocument call .update() on it with a single field (of a larger object) and it is not accepted.

Sample data and security rules n/a

<-- include/attach/link to some json sample data (or provide credentials to a sanitized, test Firebase project) -->

Debug output

* Errors in the JavaScript console *

* Output from firebase.database().enableLogging(true); *

* Screenshots *

Expected behavior


I would expect that I can update a single field on a larger object as per the Firestore docs

Actual behavior

Typescript is telling me:

Argument of type '{ votes: number; }' is not assignable to parameter of type 'Post'.
  Property 'text' is missing in type '{ votes: number; }'.

That is to say, "We're looking for you to pass in the whole Post object, not just one field."

Most helpful comment

It seems you can also do:

userRef.set(data, {merge: true});

As documented here: https://firebase.google.com/docs/firestore/manage-data/add-data

Am I missing something which would make this different than update(data, {create: true})?

EDIT: Nevermind, this project uses the NodeJS client instead of the web client. (odd that they would implement set(...{merge: true}) in one, and update(...{create: true}) in the other)

All 8 comments

Not only the partial typescript issue but it appears .update() is not creating a document if it doesn't already exist. .set() works.

const path = `users/${this.currentUserId}`; // Endpoint on firebase

    this.userDocument = this.afs.doc<any>(path);

    const data = {
      email: this.authState.email,
      name: this.authState.displayName
    }

    this.userDocument.update(data) // .set() works correctly right here...
      .catch(error => console.log(error));
  }

According to the Node.js documentation for "Set a document" at https://firebase.google.com/docs/firestore/manage-data/add-data:

The option to merge data is not yet available for Node.js. Instead, call the update method and pass the option to create the document if it's missing.

I couldn't find that feature documented anywhere, but tried appending "create: true" to the update request and it works swimmingly.

// Updates "widget-1" doc if it exists, or creates it if it doesn't
db.collection('widgets').doc('widget-1').update({
   thingamajig: true
}, { create: true });

@itjustwerks can you tell me why using create: true I get [ts] Expected 1 arguments, but got 2. from my linter? What could it be that I have different from you?

"angularfire2": "^5.0.0-rc.3",
"firebase": "^4.5.2"

constructor(
    private db: AngularFirestore
)

const userRef: AngularFirestoreDocument<any> = this.db.collection('users').doc(user.uid);
const data: User = {
    // some data
};
return userRef.update(data, { create: true });

Ok I got it:

[...]
const userRef = this.db.firestore.collection('users').doc(user.uid);
[...]
return userRef
    .get()
    .then(doc => {
        if (!doc.exists) {
            userRef.set(data);
        } else {
            userRef.update(data);
        }
    })
    .catch(err => {
        console.log(`[LOGIN] ${err}`);
    });
[...]

@Azmos , my bad. The {create: true} 2nd parameter is only applicable to the firebase-admin Node.js library for some reason. I just tried it myself for the web today and got the same error as you. I ended up doing the set in the catch block if there was an error on the update, but your solution is better for sure. Thanks!

It seems you can also do:

userRef.set(data, {merge: true});

As documented here: https://firebase.google.com/docs/firestore/manage-data/add-data

Am I missing something which would make this different than update(data, {create: true})?

EDIT: Nevermind, this project uses the NodeJS client instead of the web client. (odd that they would implement set(...{merge: true}) in one, and update(...{create: true}) in the other)

Tried once again and neither of them work on my code, in my case checking "manually" if the document exists is the only way to achieve that.

Tried once again and neither of them work on my code, in my case checking "manu

Was this page helpful?
0 / 5 - 0 ratings