13

As far as I know - In order to check whether a document exists or not, I should use the get function and see if it does.

My question is about checking while updating - Is it possible? (Considering that the document might be gone when the update occurs).

I have tried to update an empty document and I got an error which says that the document doesn't exist, but I think this might not be the successful way to check this.

Tal Barda
  • 4,067
  • 10
  • 28
  • 53

5 Answers5

28

There are a few ways to write data to Cloud Firestore:

  • update() - change fields on a document that already exists. Fails if the document does not exist.
  • set() - overwrite the data in a document, creating the document if it does not already exist. If you want to only partially update a document, use SetOptions.merge().
  • create() - only available in the server-side SDKs, similar to set() but fails if the document already exists.

So you just need to use the correct operation for your use case. If you want to update a document without knowing if it exists or not, you want to use a set() with the merge() option like this (this example is for Java):

// Update one field, creating the document if it does not already exist.
Map<String, Object> data = new HashMap<>();
data.put("capital", true);

db.collection("cities").document("BJ")
        .set(data, SetOptions.merge());
Tal Barda
  • 4,067
  • 10
  • 28
  • 53
Sam Stern
  • 24,624
  • 13
  • 93
  • 124
  • Can you write this one in Java? I'm using Firebase for Android actually. – Tal Barda Oct 12 '17 at 16:32
  • Thanks. I'll ask you what I have asked under the answer above: Can I detect if the operation failed specifically because the document doesn't exist? – Tal Barda Oct 12 '17 at 17:09
  • 1
    Yes, in the Android client the failure comes as a [FirebaseFirestoreException][1] which contains a [Code][2]. In this case you'll see Code.ALREADY_EXISTS. [1]: https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/FirebaseFirestoreException [2]: https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/FirebaseFirestoreException.Code – Gil Gilbert Oct 12 '17 at 19:44
  • Will update still fail if a field does not exist in the document? So if I had a document {firstname: "John"} and i call doc.update({lastname: "Doe"}) would that be ok? – DevShadow Mar 07 '18 at 20:52
  • @DevShadow that will succeed. – Sam Stern Mar 08 '18 at 17:03
  • In Javascript, the second argument is simply an Object, so it would become: `db.collection("cities").document("BJ").set(data, {merge: t rue});` I am writing it here because this question is the first result on Google for `firestore update if exists` – Muhammad bin Yusrat Sep 24 '20 at 07:13
9

If you only want to perform an update if the document exists, using update is exactly the thing to do. The behavior you observed is behavior you can count on.

We specifically designed this so that it's possible to perform a partial update of a document without the possibility of creating incomplete documents your code isn't otherwise prepared to handle.

Gil Gilbert
  • 7,722
  • 3
  • 24
  • 25
  • So should I read the message in OnFailure and than detect if it's occured because the document doesn't exist? Is there a good way to detect if the update failed specifically because of this? – Tal Barda Oct 12 '17 at 15:16
  • @TalBarda see below. You should write data using the appropriate operation. – Sam Stern Oct 12 '17 at 16:25
1

The easiest way to try to update a document that does not exist is:

try {
  await db.collection('cities').doc('BJ').update('key', 'value')
} catch (error) {
  // document not exists, do nothing  
}
Jan Jarčík
  • 2,681
  • 2
  • 18
  • 21
  • thanks for reminding me try and catch. here is an example for firestore: try { return await updateDoc(refDoc, { allocatedInProjects: increment(1) }) } catch (error) { return await setDoc(refDoc, { allocatedInProjects: 1 }) } – Marcin Żmigrodzki Mar 15 '23 at 14:45
0

We can go with update and set the mask parameter to true like this: -

firestore.updateDocument("GFrom/"+data.email,data, true);
AmitNayek
  • 158
  • 1
  • 9
0

I think in such type of scenario the set() with merge: true is the best option to use. Using Flutter

firestoreInstance.collection("users").doc(firebaseUser.uid).set(
{
"username" : "userX",
},SetOptions(merge: true))
Abdur Rehman
  • 313
  • 2
  • 6