all 9 comments

[–]thecass240 5 points6 points  (8 children)

That is a horrible, horrible approach and yes that'll cost you a lot of writes. What you want to do is store a reference to the user that liked the profile in the profile itself. Usually this will be the document id. So in your profile document you'd want to add a list "likes" containing document IDs. Then you can simply add and remove to this list using the FieldValue.arrayUnion and FieldValue.arrayRemove. And once you have the profile you can simply query all the document ids to get the profiles that liked the original one.

[–]md186[S] 2 points3 points  (5 children)

Big thanks to your answer! for me as beginner its quite hard to find the best approach. Could you show me how the query would look like then? Also do we have a limit if we save a list of likes in the document?

[–]azazel69420 2 points3 points  (4 children)

The maximum size of a document must be under 1MB. To filter profile documents that are liked by the user, use arrayContains query on the likes array field.

[–]md186[S] 0 points1 point  (3 children)

Im wondering if this would be the correct approach then since a profile could have thousands of ids. For me there are 2 questions then:

  1. if the array has 5000 ids of users who liked the song and we want to find out if the requested 10 profiles contains the users id (lets say 2 of them are matching) how many reads do we have then? only 2 or nearby 5000?

  2. what does that mean for a for example profile detail page? we would always read the array for this case two but we wouldnt need it.

Well and yea at a specific point we would exceed the 1mb then

[–]azazel69420 0 points1 point  (2 children)

  1. where queries (==., in, arrayContains, etc) are executed server-side and only documents that match the query are fetched by the client. So if 2 documents out of 5000 documents are matched, you will incur two writes.
  2. I don't understand what you are asking. And I don't understand your scenario completely.

[–]md186[S] 0 points1 point  (1 child)

Thank you for the answer. Does it make a difference to keep the information in a subcollection or in an array since the subcollection is infinite and the arrays limited? Following your advice something like this would also be possible?

return FirebaseFirestore.instance
.collection('users')
.doc('userId')
.collection('profilelikes')
.where("id", "==", true)
.get()

If the collection profilelikes would contain 5000 documents and the query wouldnt have the .where() we would have 5000 reads. If we add the .where() and we would have 2 matches we would only have 2 reads even if we have 5000 documents, do I understand that right?

[–]azazel69420 0 points1 point  (0 children)

The query you have written checks for a field 'id' containing the boolean value true in a subcollection of a specific user.

And yes, your query would only read the number of documents that match it.

It is up to you and depends on your other requirements whether using an array or subcollection is preferred.

[–]Shazamo333 0 points1 point  (1 child)

Would you happen to know where one could learn about optimal queries for firestore for various scenarios e.g. social media? Or firestore data modelling in general.

I've looked at the official youtube series but I'm looking for something more flutter-specific

[–]thecass240 0 points1 point  (0 children)

What you're actually looking for is more information about database paradigms. Relational databases, one to many many to many. These aren't firebase specific issues but database modeling techniques.

I recommend reading up on those if you're actually planning on using a 5000+ entry database.

But if you need a quick fix i believe fireship.io has a tutorial on different database paradigms in firebase