I’m looking to build an app that functions like a dating app:
- User A fetches All Users.
- User A removes Users B, C, and D.
- User A fetches All Users again – excluding Users B, C, and D.
My goal is to perform a query that does not read the User B, C, and D documents in my fetch query.
I’ve read into array-contains-any
, array-contains
, not-in
queries, but the 10 item limit prevents me from using these as options because the "removed users list" will continue to grow.
2 workaround options I’ve mulled over are…
-
Performing a paginated fetch on All User documents and then filtering out on the client side?
-
Store all User IDs (A, B, C, D) on 1 document in an array field, fetch the 1 document, and then filter client side?
Any guidance would be extremely appreciated either on suggestions around how I store my data or specific queries I can perform.
2
Answers
You can do it the other way around.
Instead of a
removed
orignored
array at your current user, you have an array ofignoredBy
orremovedBy
in which you add your current user.And when you fetch the users from the users collection, you just have to check if the requesting user is part of the array ignoredBy. So you don’t have tons of entries to check in the array, it is always just one.
Firestore may get a little pricey with the Tinder model but you can certainly implement a very extensible architecture, well enough to scale to millions of users, without breaking a sweat. So the user queries a pool of people, and each person is represented by their own document, this much is obvious. The user must then take an action on each person/document, and, presumably, when an action is taken that person should no longer reappear in the user’s queries. We obviously can’t edit the queried documents because there could be millions of users and that wouldn’t scale. And we shouldn’t use arrays because documents have byte limits and that also wouldn’t scale. So we have to treat a collection like an array, using documents as items, because collections have no known limit to how many documents they can contain.
So when the user takes an action on someone, consider creating a new document in a subcollection in the user’s own document (user A, the one performing the query) that contains the person’s
uid
, and perhaps a boolean to determine if they liked or disliked that person (i.e.liked: true
), and maybe a timestamp for UI purposes. This new document is the item in your limitless array.When the user later performs another query, those same users are going to reappear in the results, which you need to filter out. You have no choice but to check if each person’s
uid
is in this subcollection. If it is, omit the document and move to the next. But if your UI is configured like Tinder’s, where there isn’t a list of people to scroll through but instead cards stacked on top of each other, this is no big deal. The user will only be presented with one person at a time and they won’t know how many you’re filtering out behind the scenes. With a paginated list, the user may see odd behavior like uneven pages. The drawback is that you’re now paying double for each query. Each query will cost you the original fetch and the subcollection-check fetch. But, hey, with this model you can scale to millions of users without ever breaking a sweat.