Reputation: 429
I am designing a social app using java android with FireStore as backend. In the beginning, Firestore modeling can be a big change, as I have read I am trying to keep Documents small and not to make too many subcollections, let´s suppose the following scenario:
A User can create a few profiles
A profile has interests
A user can follow or unfollow many profiles so a profile can be followed by a lot of users
uid: uidUserOne
name: jeff
idProfile: idProfileOne
name: nameProfileOne
interests: { yoga: true, running: true, climbing: true }
createdBy: uidUserOne
Here start my doubts not sure how to model de Follow/unfollow functionality, I have three options in mind:
uid: uidUserOne
idProfile: idProfileOne
One document maps the followers of each profile, I save the user UIDs that follow the profile in an array.
idProfile: idProfileOne
followers: { uidUserOne: true, uidUserTwo: true, ...}
One document maps the follows of each user, I save the profiles ids that are followed by the user in an array
uid: uidUserOne
follows: { idProfileOne: true, idProfileTwo: true, ...}
I would like to know which options are the best, A B r C also if it can be a better one... probably
And I have another doubt, how can I do the following query:
Let's say I am user One and I already follow two profiles with yoga interest so I want to list, profiles with yoga interest which I do not follow yet, not sure how to accomplish this.
Upvotes: 1
Views: 397
Reputation: 138979
As far as I can see, your answer provides a solution to the following system that is related to the Realtime Database, while your question is related to Firestore. Please note that both databases are a part of Firebase but both are two different products, with two different mechanisms.
And to answer your questions:
Option A. Make a collection in which each document maps a single user that follows one profile relationship
Even if this solution sounds a little costly, since everything in Firestore is related to the number of reads, might be a solution to take into consideration for an app with a reasonable number of users/followers. I have answered a few years ago a similar question, so please check my answer below:
However, imagine the cost of reading a user who has 1 MILLION followers?
Option B. One document maps the followers of each profile, I save the user's UIDs that follow the profile in an array.
That's also a solution to go ahead with. But also remember that the documents have limits, so I'm afraid that 1 MILLION UIDs doesn't fit into a single document. However, you can create a new document every time you reach the limitation. I have created a library that can help you check the document size against the 1 MiB maximum size:
Option C. One document maps the follows of each user, I save the profiles ids that are followed by the user in an array
This option is the same as option B.
Let's say I am user One and I already follow two profiles with yoga interest so I want to list, profiles with yoga interest which I do not follow yet, not sure how to accomplish this.
In this case, the "collection" solution is the one to go ahead with because you can add an array of interests to each UID document that follows a user.
Edit:
Let's assume you are interested in following users who have interests in yoga that you don't follow. Here is a schema that can help you achieve that:
Firestore-root
|
--- users (collection)
| |
| --- $uid (document)
| |
| --- interests: ["yoga", "running", "climbing"]
|
--- followers
|
--- $uid (document)
|
--- userFollowers (sub-collection)
|
--- $followerUid (document)
|
--- //Data
To get the desired results, you need two queries. One to get the users that are interested in yoga, and the second one, to get only the one that you don't follow. Actually, you need to check which user is not present in the userFollowers sub-collection. To check if a user doesn't exist, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
DocumentReference followerUidRef = rootRef
.collection("followers").document(uid)
.collection("userFollowers").document(followerUid);
followerUidRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (!document.exists()) {
//Follow the user
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
Upvotes: 1