我想检索某个集合中的所有子元素,除了一个特定的子元素。我有数据库"用户"它由多个用户id组成。
"users"
|- "userId1"
|- "userId2"
|- "userId3"
等等。我现在只想检索"userId1"one_answers";userId3"并排除"userid2"。我已经知道如何获取userId2,因为我已经将它存储在另一个数据库"blocked-users"中。该数据库由userid组成,构建方式如下:
"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)
我现在如何排除快照。键从这个函数中获取?:
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
})
}
}
我找到了一个方法。在Firebase规则中,我这样解决这个问题:
"$users": {
"$uid": {
".read": "auth != null && !(root.child('blocked-users').child(auth.uid).hasChild($uid))",
".write": "auth != null"
}
}
它是这样读的:当auth不为空并且用户不在他们想要查找的用户的阻塞用户集合中时,允许用户读取用户的数据。
通常无法从查询中排除一个(或几个)节点。您要么必须加载整个users
节点并过滤掉您不的用户在你的应用程序代码中,或者你将不得不加载你做的用户要一个一个。
唯一的变化是,如果您可以使用查询来分割您想要和不想要的子节点。例如,如果您有99个用户(为了简单起见,从user01
到user99
),并且除了一个用户(比如user42
)之外不会读取所有用户,那么您可以使用两个查询:
usersRef.queryOrderedByKey().queryEnding(beforeValue: "user42")
和
usersRef.queryOrderedByKey().queryStarting(afterValue: "user42")
我不认为在这里使用这种方法有什么好处,因为与过滤应用程序代码中的一个节点相比,处理两个查询可能(稍微)效率较低,并且需要更多的代码。