[英]Bypassing Firebase IN: limit in Swift
我有一個查詢,我正在使用 Google 的 Firestore 進行查詢,在那里我從一個集合中查詢帖子。 這是 .network 上所有帖子的中央集合,但我希望能夠過濾來自服務器的內容,這樣處理/過濾就不會在客戶端發生。 本質上,我只想從用戶關注的帳戶中獲取帖子提要。
創建該數組很容易。 當用戶登錄時,它會下載用戶遵循的 UID 數組。 從理論上講,這個數組可能很長。 Firestore 有這個方便的“.whereField”選項,可以像這樣使用 in: 過濾字符串數組的外觀。
.whereField("userUID", in: auth.userFollowedAccounts!)
它工作得很好,但根據文檔,當使用 in: 時,Firestore 只允許數組中的 10 個項目。 這會導致問題,因為我希望用戶能夠關注 10 個以上的帳戶。 我看到了一些其他語言的其他解決方案,通過拼接數組或通過所有選項對 go 進行一些巧妙的循環來解決這個問題。 不幸的是,我似乎找不到 Swift 的解決方案。希望有人能幫我集思廣益解決這個問題。
// 完整代碼塊
func getData() {
let db = Firestore.firestore()
db.collection("posts")
.order(by: "dateCreated", descending: true)
.whereField("userUID", in: auth.userFollowedAccounts!)
.limit(to: 10)
.getDocuments { (snap, err) in
if err != nil {
print((err?.localizedDescription)!)
return
}
self.post.removeAll()
for i in snap!.documents {
let data = Post(id: i.documentID, username: i.get("username") as? String, fullName: i.get("fullName") as? String, profilePictureURL: i.get("profilePictureURL") as? String, link: i.get("link") as? String, location: i.get("location") as? String, postImage: i.get("postImage") as? String, isVerified: i.get("isVerified") as? Bool, caption: i.get("caption") as? String, likeCounter: i.get("likeCounter") as? Int, dateCreated: i.get("dateCreated") as? String, userUID: i.get("userUID") as? String, isAdmin: i.get("isAdmin") as? Bool, pronouns: i.get("pronouns") as? String)
self.post.append(data)
}
self.lastDoc = snap!.documents.last
}
}
如果您有任何問題,請告訴我。
下面是一個使用 Firestore async/await 調用來縮短代碼的簡單示例。
問題中未包含 Firebase 結構(請在問題中包含該結構),因此我將制作一個可能與您使用的結構相似的結構
從使用用戶 uid 作為 documentId 的用戶集合開始,保留用戶名,然后將他們關注的用戶作為數組
users
uid_0
user_name: "Leroy"
following
0: uid_9
uid_1
user_name: "Biff"
following
0: uid_0
1: uid_2
在此,uid_0 跟隨 uid_9,uid_1 跟隨 uid_0 和 uid_2
然后是一個帖子集合片段
posts
post_0
post_msg: "Post 0 from uid_0"
post_uid: "uid_0"
post_1
post_msg: "Post 0 from uid_1"
post_uid: "uid_1"
post_2
post_msg: "Post 1 from uid_0"
post_uid: "uid_0"
這些帖子有一條消息和發布它的用戶的 uid。
然后是代碼。
func getPostsOfUsersIFollow() {
let usersCollection = self.db.collection("users")
let postsCollection = self.db.collection("posts")
let thisUserDoc = usersCollection.document("uid_1") //me
Task {
do {
let userResult = try await thisUserDoc.getDocument()
let usersIFollow = userResult.get("following") as? [String] ?? []
print(usersIFollow) //outputs the list of users uid's I follow
for uid in usersIFollow {
let usersPosts = try await postsCollection.whereField("post_uid", isEqualTo: uid).getDocuments()
for postDoc in usersPosts.documents {
let postMsg = postDoc.get("post_msg") as? String ?? "no msg"
print("post_id: \(postDoc.documentID) uid: \(uid) posted msg: \(postMsg)")
}
}
} catch {
print("need to handle error")
}
}
}
如果我是用戶 uid_1,那么我關注的是 uid_0 和 uid_2。 運行此代碼時,它將首先查詢我關注的所有用戶(uid_0、uid_2),然后遍歷該列表(可以是任意數量的用戶)以查詢每個用戶的帖子,以及 output 那些發布到控制台。
因此,如果 uid_0 有 3 個帖子而 uid_2 有 3 個帖子,那么最終的 output 將如下所示
["uid_0", "uid_2"]
post_id: post_0 uid_0 posted msg: Post 0 from uid_0
post_id: post_4 uid_0 posted msg: Post 1 from uid_0
post_id: post_6 uid_0 posted msg: Post 2 from uid_0
post_id: post_2 uid_2 posted msg: Post 0 from uid_2
post_id: post_5 uid_2 posted msg: Post 1 from uid_2
post_id: post_9 uid_2 posted msg: Post 2 from uid_2
在這種情況下,我 output 進行控制台,但在代碼中,您可能有一些 class 來存儲 uid、名稱和發布,然后填充一個數組,該數組支持 tableView 或使用該數據的集合
class UserPostClass {
var uid = ""
var postId = ""
var userName = ""
var postMsg = ""
}
var userPostArray = [UserPostClass]()
然后一旦數組被填充,重新加載你的 tableView,視圖等。
這里的一個問題是確保 UI 是響應式的——對於小型數據集,這將按原樣工作,但如果您要加載數千篇文章(不要那樣做),您可能需要對數據進行分頁以將其分成更小的塊。
另一件需要注意的事情是沒有排序,所以你可能想要添加一個 orderBy 子句
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.