Reputation: 1120
I have two Firestore collections, Users
and Posts
. Below are simplified examples of what the typical document in each contains.
*Note that the document IDs in the
friends
subcollection are equal to the document ID of the corresponding user documents. Optionally, I could also add a uid
field to the friends
documents and/or the Users
documents. Also, there is a reason not relevant to this question that we have friends
as a subcollection to each user, but if need-be we change it into a unified root-level Friends
collection.
This setup makes it very easy to query for posts, sorted chronologically, by any given user by simply looking for Posts
documents whose owner
field is equal to the document reference of that user.
I achieve this in iOS/Swift with the following, though we are building this app for iOS, Android, and web.
guard let uid = Auth.auth().currentUser?.uid else {
print("No UID")
return
}
let firestoreUserRef = firestore.collection("Users").document(uid)
firestorePostsQuery = firestore.collection("Posts").whereField("owner", isEqualTo: firestoreUserRef).order(by: "timestamp", descending: true).limit(to: 25)
My question is how to query
Posts
documents that haveowner
values contained in the user'sfriends
subcollection, sorted chronologically. In other words, how to get the posts belonging to the user's friends, sorted chronologically.
For a real-world example, consider Twitter, where a given user's feed is populated by all tweets that have an owner property whose value is contained in the user's following list, sorted chronologically.
Now, I know from the documentation that Firestore does not support logical OR queries, so I can't just chain all of the friends together. Even if I could, that doesn't really seem like an optimal approach for anyone with more than a small handful of friends.
The only option I can think of is to create a separate query for each friend. There are several problems with this, however. The first being the challenges presenting (in a smooth manner) the results from many asynchronous fetches. The second being that I can't merge the data into chronological order without re-sorting the set manually on the client every time one of the query snapshots is updated (i.e., real-time update).
Is it possible to build the query I am describing, or am I going to have to go this less-than optimal approach? This seems like a fairly common query use-case, so I'll be surprised if there is not a way to do this.
Upvotes: 1
Views: 861
Reputation: 18565
The sort chronologically is easy provided you are using a Unix timestamp, e.g. 1547608677790
using the .orderBy
method. However, that leaves you with a potential mountain of queries to iterate through (one per friend).
So, I think you want to re-think the data store schema.
Take advantage of Cloud Functions for Firebase Triggers. When a new post is written, have a cloud function calculate who all should see it. Each user could have an array-type property containing all unread-posts
, read-posts
, etc.
Something like that would be fast and least taxing.
Upvotes: 2