2

I have a Firestore structure with nested subcollections like this:

  • Projects
    • Visits
      • Observations → Can have a reference to an Image in the Firebase Storage

So I have the following use cases:

1. When I delete an Observation I need to remove the associated image from the Storage.

2. When I delete a Visit I need to delete all it's Observations and their respective images.

3. When I delete a Project I need to delete all it's Visits, then all it's Observations and their respective images.

  • Also I'm doing it in the client, iterating by all the structure (get all visits, then get all observations...).

I'm aware that resolving the use cases 2 and 3 in the client is not a good option based on the Firebase Team recommendations so it should be resolved using Cloud Functions, right?

According to official documentation deleting a collection and all it's subcollections can be done using firebase_tools.firestore.delete but I think this solution will not satisfy the use case 1, I'm right? (Also I'm reading that using firebase_tools will lag a lot).

Another option could be doing the iteration in the Cloud and delete every item there.

I don't have too much experience with Firebase so I really don't know what's the best approach to solve this problem...

Thanks in advance!

Fran Fox
  • 501
  • 5
  • 15
  • 1
    *is not a good option* - why? What leads you to think you cannot/should not delete from the client? When you perform that task is something not working as expected? What does "lag a lot" mean? Firebase functions are called on a background thread so the use would not see any "lag" in general. So the question is a bit vague - can you clarify? – Jay Aug 28 '21 at 16:52
  • 1
    This [answer](https://stackoverflow.com/questions/49125183/how-delete-a-collection-or-subcollection-from-firestore/49125226) might help. – Alex Mamo Aug 29 '21 at 10:00
  • Thanks @Jay I've read that remove it in the client has negative security and performance implications but as I don't have too much experience in this topic I can't be more clear. I think Firebase Team recommend it and someone told me that, even if my code was working, it wasn't good to do it in the client. Same thing with the "lag a lot", I've read it and I'm just want to be sure about my options. – Fran Fox Aug 30 '21 at 06:15
  • Thanks @AlexMamo It seems doing it in the client is a valid solution if you have small collections. – Fran Fox Aug 30 '21 at 06:20
  • Hmm. That has not been my experience. Can you point us to something in the documentation, or maybe a post here on SO showing that deleting from the client has those issues - bad security and creates lag? – Jay Aug 30 '21 at 17:10
  • Hi Jay, somenone told me in a private group but in the Firebase docu. tell us: "If you need to delete entire collections, do so only from a trusted server environment. While it is possible to delete a collection from a mobile/web client, doing so has negative security and performance implications." https://firebase.google.com/docs/firestore/manage-data/delete-data#collections – Fran Fox Sep 01 '21 at 07:00
  • 1
    Yes that is stated in the docs but context is needed for clarity. It is perfectly acceptable to delete a collection from the client. HOWEVER, a clear understanding of the ramifications is important; Deleting a collection requires deleting the documents. In some cases that would mean downloading ALL of the documents to get their path which could overwhelm the device. – Jay Sep 01 '21 at 18:15
  • Along with that, a big download could drive up costs along with possibly affecting the user experience. So if you need to delete a collection that has 10 documents and will not scale, no problem. But if that collection scales to 1M documents that's a different use case and has a different solution. – Jay Sep 01 '21 at 18:15

2 Answers2

3

As stated in the current documentation, deleting from the client is not advised. However, that statement is a bit of an absolute and really needs clarity; it's very use case dependent.

The big picture from Firebase:

There is no single operation in the API to delete an entire collection. Instead a collection comes into existence once a first document is added to it, and a collection disappears once the final document is deleted from it.

So, deleting via the client is possible and is sometimes a solution

HOWEVER, a clear understanding of the ramifications is important. There are many but here are some to consider:

Deleting a collection requires deleting the documents. In some cases that would mean downloading ALL of the documents to get their path which could overwhelm the device.

Along with that, a big download could drive up costs along with possibly affecting the user experience.

To be clear

deleting a collection is ok but may not scale well depending on the size of the collection

e.g. if you need to delete a collection that has 10 documents and will not scale, no problem. But if that collection scales to 1M documents that's a different use case and has a different solution.

So wrapping back to the question:

  1. When I delete an Observation I need to remove the associated image from the Storage.

The key here is "an observation" meaning 1. Yes, it is perfectly acceptable to delete this from the client as '1' is well... '1' and does not scale.

  1. When I delete a Visit I need to delete all it's Observations and their respective images.

This is use case dependent: as of now you're getting all the documents and deleting via iteration. That's what should be avoided because it doesn't scale with an open ended number of documents ...but... if you've limited visits to say 100, then it's not going to scale past that so deleting from the client is ok. If there is NO limit, then deleting from a cloud function is the way to go.

  1. When I delete a Project I need to delete all it's Visits, then all it's Observations and their respective images.

This really depends on what limits you've set for the data within a Project. If it's limited to X number of documents and X is a reasonable number then deleting from the client is okay. However, if there are no limits, leveraging cloud functions is your best bet.

There is NO reason why the two can't be combined as well. For 1, delete from the client. For 2 & 3 delete via cloud functions if the data can scale to a large number.

All that being said, Cloud functions have limitations too - the call can take a while so if there are client side queries running, you can end up with fragmented data. Also, you don't have a status or control over the length of time it will take so it could conceivably time out, then you're in a weird state with some stuff deleted and some stuff not.

Lastly, the cloud based deletions are not transactional, so some data may be deleted and some may not. That should be very very rare but the potential exists.

Jay
  • 34,438
  • 18
  • 52
  • 81
1

You should do the delete operations using Cloud Functions.

And there's no problem with the first use case as you can still delete a collection or a firebase storage image with Cloud Functions.

Victor Eronmosele
  • 7,040
  • 2
  • 10
  • 33
  • 1
    This answer jumps to a conclusion that may be incorrect. More information would be needed before assuming that Cloud Functions are the only option. Deleting data is built into the API so only leveraging Cloud Functions would be situational. I think the question needs clarity before going down this path. – Jay Aug 28 '21 at 16:57