What is the best solution to do this?
I know that everyone is looking for the best solution but in the land of NoSQL databases, there is no best solution. There are many ways in which you can model a database for an app like yours and have the same result and and I'll demonstare you why. Before that, please take a look at my answer from this post, to have a better understanding about the concept of "perfect", "the best" or "the correct" solution in case of a NoSQL database.
The best solution is, just kidding :) A recommend way in which you can achieve this favorite feature list that you are look for, is to use arrays
. Your database schema might look like this:
Firestore-root
|
--- users (Collection)
| |
| --- uid (document)
| |
| --- favoriteLocations: ["favoriteLocationId", "favoriteLocationId"]
|
--- locations (Collection)
|
--- locationId (document)
|
--- //Location details
As you can see, the favoriteLocations
array holds only location ids. So in order to get location details, you should get those ids and make an extra database get()
call.
Another approach would be, instead of storing an array of location ids, to store an array of maps or an array of location objects. This option works fine if you have a reasonable number of favorite locations, let's say 5, 10 or even 50 but not 500. If you'll need to store 500 location, what is the reason you'll store a location as favorite?
An important thing to remember in this case, is that the documents have limits. So there are some limits when it comes to how much data you can put into a document. According to the official documentation regarding usage and limits:
Maximum size for a document: 1 MiB (1,048,576 bytes)
As you can see, you are limited to 1 MiB total of data in a single document. When we are talking about storing text, you can store pretty much but as your array getts bigger, be careful about this limitation.
If you want to store more data that a single documents allow you to store, then you should use collections. This way you can create a subcollection under each user object that will hold as documents, location objects. Your database structure should like something like this:
Firestore-root
|
--- users (Collection)
| |
| --- uid (document)
| |
| --- favoriteLocations (Collection)
| |
| --- favoriteLocationId (document)
| |
| --- //Location details
|
--- locations (Collection)
|
--- locationId (document)
|
--- //Location details
To query a database that looks like this, please use the following lines of code:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference favoriteLocationsRef = rootRef.collection("users").document(uid).collection(favoriteLocations);
favoriteLocationsRef.get(/* ... */);
Another approach would be to denomalize your data and create your favoriteLocations
subcollection, as a top-level collection like this:
Firestore-root
|
--- users (Collection)
| |
| --- uid (document)
| |
| --- //User details
|
--- locations (Collection)
| |
| --- locationId (document)
| |
| --- //Location details
|
--- favoriteLocations (Collection)
|
--- uid (document)
|
--- userFavoriteLocations (collection)
|
--- favoriteLocationId (document)
|
--- //Location details
The corresponding query should look like this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference favoriteLocationsRef = rootRef.collection("favoriteLocations").document(uid).collection(userFavoriteLocations);
favoriteLocationsRef.get(/* ... */);
Or an even easier way, would be like this:
Firestore-root
|
--- users (Collection)
| |
| --- uid (document)
| |
| --- //User details
|
--- locations (Collection)
| |
| --- locationId (document)
| |
| --- //Location details
|
--- favoriteLocations (Collection)
|
--- locationId (document)
|
--- uid: "uid"
|
--- //Other location details
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = rootRef.collection("favoriteLocations").whereEqualTo("uid", uid);
favoriteLocationsRef.get(/* ... */);
As you can see, I have added the uid of the user as a property of the location object so you can simply get all favorite locations a particular user has.
It's up to you to choose which solution is "best" for your app use-case :)
P.S. Please also take a look at my answer from this post where I have explained more about collections
, maps
and arrays
in Firestore.