AkbarB
AkbarB

Reputation: 530

Updating all the references to an image url in Cloud Firestore when the image is updated using Flutter

In my Flutter app, I have a userData collection on Cloud Firestore where I store user's data including name, image url, etc.. The user can create posts, add comments to post, etc. similar to any other social apps out there and so I have multiple other collections where the user's info is stored including the link to their profile image.

Let's say if the user adds a comment to a post, I save their name, profile image url and comment text as a document inside "postComment" collection and then I display his/her profile image, name and the comment text on the screen by reading this collection and document.

Now, if the user updates their profile image or even their name which will be reflected in the userData collection, I need to make sure that their name and image url are updated in all other collections as well.

What's the easiest and least costly way to do that? Do I need to loop through all my collections and their documents and update the field values, or is there like a simple cloud function that can handle this?

Thanks!

Upvotes: 1

Views: 1417

Answers (3)

LeadDreamer
LeadDreamer

Reputation: 3499

I also store user profile images in Firestore Storage, BUT I use a very consistent schema to make the images easy to "guess": When I have a document such as "/People/{userID}", and within the document is a field "image" which stores the URL to the image... ...then I store it in Firestore at the path "People/{userID/image/image.jpg" (eg). This way it is trivial to generate a StorageRef to it, and a downloadURL.

All the other uses of it always are to the now-standardized URL. Change the image in Storage; all references update.

For most "user" applications, the only use of the image is to feed it to a web-page, so just the URL is needed, and let the browser do the rest of the work.

As Fattie somewhat more aggressively stated, generally all you need is the URL. But following by itself that means you still would have to find all the references and update them if the user changes the URL. Saving a copy in Firestore Storage, and using that consistent URL, means all references will be "updated" just by changing what is stored at that location. Disadvantage is it will count as a storage read when fetched.

I'm finding duplicating data in NoSQL is great when it's fairly static - created once, and not dynamically changed (which is a LOT of cases). If your application doesn't fit that, it's better to store a reference to the source-of-truth, and incur the cost of the "lookup".

Here's a couple utilities I use to make this easier:

export const makeStorageRefFromRecord = (
  record,
  key = null,
  filename = null
) => {
  return FirebaseStorage.ref(
    record.ref.path + (key ? "/" + key : "") + (filename ? "/" + filename : "")
  );
};

export const makeFileURLFromRecord = (record, key = null, filename = null) => {
  return FirebaseStorage.ref(
    record.ref.path + (key ? "/" + key : "") + (filename ? "/" + filename : "")
  ).getDownloadURL();
};

("key" is essentially the fieldname) remember the refpath is a string of the "/" separated collection/document path to the record, and is completely knowable in a simple situation, such as "People/{userID}". If you keep this internal, you can use "filename" as simple as "image.jpg" so it's always the same - it's unique, because of the path.

Upvotes: 3

Siddharth Agrawal
Siddharth Agrawal

Reputation: 3146

There are multiple ways to do that.
The best way to do that is instead of storing the profile picture image again and again, you can store document references. If you are storing the images as base64, this would also save a lost of space and is cost efficient.

Another way of doing it is less efficient but you can store the image in firestore and refer it from there.
Both of these are from refereces
The last way of doing it and probably the most inefficient is by querying. You can go to that collection of post (Or if you store each post as a collection, loop through all of them) and then add a where filter and search for the imageURL or more safely a unique ID and then you can change them all one by one These are the ways that I know

Upvotes: 0

Doug Stevenson
Doug Stevenson

Reputation: 317427

Do I need to loop through all my collections and their documents and update the field values

Minimally, yes, that's what you have to do.

or is there like a simple cloud function that can handle this?

You can certainly write your own Cloud Function to do this as well. There is not an existing function that will just do what you want - you have to code it.

Alternatively, you can just store the URL is one document, store the ID of that document in the other documents that need to refer to it, and have the client make an query for the single document with the URL you need.

Upvotes: 0

Related Questions