Firebase Firestore returning true on failed document delete

Viewed 3731

I have an app which uses Firebase's Firestore for persistence. I am using Material's Snackbar for notifications. I have in my service..

deleteProvider(data) {
    return this.db.collection(data.table).doc('xzc').delete();
  }

Where the data param is simply an object containing the table which I want to perform the action on and the id of the document I wish to delete.

data: { table: 'providers', id: 'some firebase identifier'}

And in my component

onDeleteEntry(event) {
    if (event.table === 'providers') {
      this.providerService.deleteProvider(event)
        .then(() => {
          this.snackBar.open('Provider deleted');
        })
        .catch((error) => {
          this.snackBar.open('Error deleting provider', error);
        });
    }
  }

This deletes the document perfectly, but on testing the failed case, it returns true.

For example, if I hard-code 'xyz' into the .doc('xyz') method. The response calls my next() method, rather than my my catch().

deleteProvider(data) {
    return this.db.collection(data.table).doc('xyz').delete();
  } // returns true on a non-existent document

The Firebase docs emphasise the fact that nested collections will remain after deletion but other than that, the basic functionality of deleting a document is simple and doesn't give very much information other than

db.collection("cities").doc("DC").delete().then(function() {
    console.log("Document successfully deleted!");
}).catch(function(error) {
    console.error("Error removing document: ", error);
});

What am I missing?

TIA

2 Answers

Currently, delete does not fail if a document doesn't exist. In a way, this is inconsistent with create, which does fail if it exists beforehand.

However, it looks like this feature is/was planned. In Java SDK, delete can take a Precondition object:

  /**
   * Deletes the document referred to by this DocumentReference.
   *
   * @param options Preconditions to enforce for this delete.
   * @return An ApiFuture that will be resolved when the delete completes.
   */
  @Nonnull
  public ApiFuture<WriteResult> delete(@Nonnull Precondition options) {
    WriteBatch writeBatch = firestore.batch();
    return extractFirst(writeBatch.delete(this, options).commit());
  }

In Precondition, there is a helper method:

  /**
   * Creates a Precondition that enforces that a document exists.
   *
   * @param exists Whether the document should exist.
   * @return A new Precondition
   */
  // TODO: Make public once backend supports verify.
  @Nonnull
  static Precondition exists(Boolean exists) {
    return new Precondition(exists, null);
  }

Note that is not public. The comment says it lacks backend support. Only Firestore team knows the current status of it.

"exists" precondition works for me

    const batch = db.batch();
    const toDeleteRef = db.collection("somecollection").doc("someid");
    const counterRef = db.collection("somecollection").doc("count");
    batch.delete(toDeleteRef, {exists:true});
    batch.set(counterRef, {value:firestore.FieldValue.increment(-1)}, {merge:true});
    await batch.commit();
Related