I am using Firebase Firestore with Swift and SwiftUI. I have two collections Users and Tweets. Each Tweet store the userId of the user who tweeted. I want to fetch all the tweets along with the user information associated with tweet. Since both are stored in different collections at the root level, this poses a problem. Here is one of the solutions.
private func populateUserInfoIntoTweets(tweets: [Tweet]) {
var results = [Tweet]()
tweets.forEach { tweet in
var tweetCopy = tweet
self.db.collection("users").document(tweetCopy.userId).getDocument(as: UserInfo.self) { result in
switch result {
case .success(let userInfo):
tweetCopy.userInfo = userInfo
results.append(tweetCopy)
if results.count == tweets.count {
DispatchQueue.main.async {
self.tweets = results.sorted(by: { t1, t2 in
t1.dateUpdated > t2.dateUpdated
})
}
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
Kinda messy!
Another way is to store the documentRef of the User doc instead of the userId.
If I store the User document reference then I am using the following code:
init() {
db.collection("tweets").order(by: "dateUpdated", descending: true)
.addSnapshotListener { snapshot, error in
if let error {
print(error.localizedDescription)
return
}
snapshot?.documents.compactMap { document in
try? document.data(as: Tweet.self)
}.forEach { tweet in
var tweetCopy = tweet
tweetCopy.userDocRef?.getDocument(as: UserInfo.self, completion: { result in
switch result {
case .success(let userInfo):
tweetCopy.userInfo = userInfo
self.tweets.append(tweetCopy)
case .failure(let error):
print(error.localizedDescription)
}
})
}
}
}
The above code does not work as expected. I am wondering there must be a better way. I don't want to store all the user information with the Tweet because it will be storing a lot of extra data.
Recommendations?