【问题标题】:Exclude certain child from retrieving Firebase从检索 Firebase 中排除某些孩子
【发布时间】:2021-11-17 04:50:46
【问题描述】:

我想检索某个集合中除一个特定孩子之外的所有孩子。我有由多个用户 ID 组成的数据库“用户”。

"users"
|- "userId1"
|- "userId2"
|- "userId3"

等等。 我现在只想检索“userId1”和“userId3”并排除“userId2”。我已经知道如何仅获取 userId2,因为我还将它存储在另一个数据库“被阻止的用户”中。这个数据库由 userIds 组成,并且是这样构建的:

"blocked-users"
|- "userId1" 
      |- "userId2"

这就是我想从检索用户中排除 userId2 的原因。假设 userId1 是 currentUser 并阻止了 userId2,我想阻止 userId1 找到 userId2。我该怎么做?

这就是我获取 userId2 的 id 的方式:

guard let currentUid = Auth.auth().currentUser?.uid else { return }

BLOCKED_USERS.child(currentUid).observe(.childAdded) { (snapshot) in
                
    print("this is the user, that should not be shown: ", snapshot.key)

我现在如何排除在此函数中获取的 snapshot.key?:

var userCurrentKey: String?
USER_REF.queryLimited(toLast: 10).observeSingleEvent(of: .value) { (snapshot) in
                    
                    guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
                    guard let allObjects = snapshot.children.allObjects as? [DataSnapshot] else { return }
                    
                    allObjects.forEach({ (snapshot) in
                        let uid = snapshot.key
                        
                        Database.fetchUser(with: uid, completion: { (user) in
                            self.users.append(user)
                            self.tableView.reloadData()
                        })
                    })
                    self.userCurrentKey = first.key
                }

这就是我为获取所有用户而调用的整个函数:

func fetchUsers() {
        
        guard let currentUid = Auth.auth().currentUser?.uid else { return }
        
        if userCurrentKey == nil {
            
            BLOCKED_USERS.child(currentUid).observe(.childAdded) { (snapshot) in
                print("these are the users that have blocked this user: ", snapshot.key)
                
                var dontShowThisUser = snapshot.key
                
                USER_REF.queryLimited(toLast: 10).observeSingleEvent(of: .value) { (snapshot) in
                    
                    guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
                    guard let allObjects = snapshot.children.allObjects as? [DataSnapshot] else { return }
                    
                    allObjects.forEach({ (snapshot) in
                        let uid = snapshot.key
                        
                        Database.fetchUser(with: uid, completion: { (user) in
                            self.users.append(user)
                            self.tableView.reloadData()
                        })
                    })
                    self.userCurrentKey = first.key
                }
            }
        } else {
            USER_REF.queryOrderedByKey().queryEnding(atValue: userCurrentKey).queryLimited(toLast: 5).observeSingleEvent(of: .value, with: { (snapshot) in
                
                guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
                guard var allObjects = snapshot.children.allObjects as? [DataSnapshot] else { return }
                allObjects.removeAll(where: { $0.key == self.userCurrentKey })
                
                allObjects.forEach({ (snapshot) in
                    let uid = snapshot.key

                    if uid != self.userCurrentKey {
                        Database.fetchUser(with: uid, completion: { (user) in
                            self.users.append(user)
                            if self.users.count == allObjects.count  {
                                self.tableView.reloadData()
                            }
                        })
                    }
                })
                self.userCurrentKey = first.key
            })
        }
    }

【问题讨论】:

    标签: swift firebase firebase-realtime-database swift5


    【解决方案1】:

    我找到了办法。在 Firebase 规则中,我这样解决这个问题:

      "$users": {
        "$uid": {
    ".read": "auth != null && !(root.child('blocked-users').child(auth.uid).hasChild($uid))",
    ".write": "auth != null"
    }
    }
    

    这读起来是这样的:当 auth 不为 null 并且用户不在要查找的用户的被阻止用户集合中时,允许用户读取用户的数据。

    【讨论】:

    • 这允许您安全地获取单个用户,但不允许您获取用户列表,这就是我如何解释“当 user2 然后搜索应用程序内的所有用户时”中的你的original question。如果此实现与您的用例匹配,很高兴听到您找到了一些可行的方法。 ?
    【解决方案2】:

    一般来说,没有办法从查询中排除一个(或一些)节点。您要么必须加载整个 users 节点并过滤掉应用程序代码中想要的用户,要么必须加载想要的用户strong> 想要一个一个。

    唯一的变化是如果您可以使用查询来分割您想要和不想要的子节点。例如,如果您有 99 个用户(为简单起见,user01user99)并且除了一个用户(例如 user42)不会读取所有用户,您可以通过两个查询来做到这一点:

    usersRef.queryOrderedByKey().queryEnding(beforeValue: "user42")
    

    usersRef.queryOrderedByKey().queryStarting(afterValue: "user42")
    

    我不认为在这里使用这种方法有什么好处,因为与过滤其中的一个节点相比,处理这两个查询的效率可能(略)低,并且处理两个查询的代码更多应用程序代码。

    【讨论】:

    • 我现在正试图通过 Firebase 安全规则来解决这个问题,因为我认为我可以这样做。我刚刚在那里遇到了一个小问题。也许这个线程中的某人可以提供帮助? link
    • @JuFa512 有更新吗?
    • 是的@FrankvanPuffelen,我找到了方法!我将在答案部分分享
    猜你喜欢
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 2017-01-28
    • 2012-11-05
    • 1970-01-01
    • 2020-01-04
    相关资源
    最近更新 更多