繁体   English   中英

绕过Firebase IN: limit in Swift

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM