ios - 仅从存在用户 UID 的节点获取特定的子值

标签 ios swift firebase firebase-realtime-database firebase-authentication

我正在开发一个群聊应用程序,但在尝试对 Firebase DB 进行特定查询时遇到了麻烦。

我需要获取房间内所有用户的个人资料照片。但只有当前用户所在的房间。

private func observeRooms() {

    let databaseRef = FIRDatabase.database().reference()
    let groupRef = databaseRef.child("groups")

    guard let uid = FIRAuth.auth()?.currentUser?.uid else {return}
    let queryRef = groupRef.queryOrdered(byChild: "participants/\(uid)").queryEqual(toValue: nil)

    queryRef.observe(.childAdded, with: { snapshot in

        let roomDict = snapshot.value as! [String: AnyObject]
        print("roomDict: \(roomDict)")
        let id = snapshot.key

        let avatar = roomDict["profilePicture"] as! String
    })
}

显然设置 queryEqual(toValue: nil) 返回当前用户不属于的所有房间——与我需要的相反。我知道反过来会检查 queryEqual(toValue: true),但是 : true 没有出现在数据库中。

这就是我在 Firebase 中将节点添加到“组”的方式:

        // Start group node for new room
        let groupRef: FIRDatabaseReference = FIRDatabase.database().reference().child("groups")
        let roomID = newRoomRef.key
        let groupRoomRef = groupRef.child(roomID)
        let groupDict = ["roomName" : roomName, "participants": [uid : true]] as [String : Any]
        groupRoomRef.setValue(groupDict)

数据结构是这样结束的:

"groups" : {
  "-KkGzZ7frbnXmImt0JpV" : {
    "participants" : {
      "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : {
        "gender" : "male",
        "handle" : "Testing",
        "name" : "Test User",
        "profilePicture" : "https://graph.facebook.com/*removed*/picture?type=large&return_ssl_resources=1",
        "status" : "F8B016"
      }
    },
    "roomName" : "Test Room"
  },

我如何才能正确地为房间中的所有用户设置 profilePicture 值,仅针对当前用户的 UID 所属的组?

最佳答案

您走在正确的轨道上。使用 queryEqual 时您的查询需要匹配数据库中实际存在的值。不幸的是,当您查询的值是复杂对象时,情况会变得复杂。事实上,即使您确实匹配了整个对象值,我也不确定该函数是否会起作用。这里的问题是,您试图通过存在的子键 来查找对象,而不是实际排序或匹配它们的值。这不太适合任何 orderBy 的用例。方法。

有几种方法可以解决这个问题,按努力排序。

首先,您可以利用 sort order只获取那些具有 UID 名称的一些对象。由于 Firebase 首先对 null 进行排序,然后是基元,最后是对象,因此您应该能够按子项排序并开始于 true (或任何原语)以获取具有该键的所有对象实例(当然,假设您没有在任何地方存储 UID: true)。

groupRef.queryOrdered(byChild: "participants/\(uid)").queryStartingAtValue(true)

其次,将 UID 复制为对象内的键,值为 true这样您就可以直接对其进行排序。请注意查询中的额外步骤。

"groups" : {
  "-KkGzZ7frbnXmImt0JpV" : {
    "participants" : {
      "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : {
        "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true,
        ...

groupRef.queryOrdered(byChild: "participants/\(uid)/\(uid)").queryEqual(toValue: true)

最后,这就是我的建议,重新考虑您的数据结构。您在这个集合集合中嵌套了大量数据,这将使您的查询和更新变得笨拙。当您 denormalize your data 时,Firebase 往往会更好地工作,更喜欢带有一些简单数据重复的扁平/浅层结构。在您的情况下,您可能有一个组集合和另一个用户集合,而不是将用户的个人资料数据存储在他们的组成员身份中,每个组仅包含其成员的 UID 列表,反之亦然.文档中的示例与您的示例非常相似,涉及聊天对话中的成员资格。届时,您的 UID(和组 ID,如果您查询的是用户)的值为 true因此您可以再次使用简单的值查询。

"groups" : {
"-KkGzZ7frbnXmImt0JpV" : {
  "participants" : {
    "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true
    ...

"users" : {
"tzfHgGKWLEPzPU9GvkO4XE1QKy53" : {
  "groups" : {
    "-KkGzZ7frbnXmImt0JpV" : true
    ...

groupRef.queryOrdered(byChild: "participants/\(uid)").queryEqual(toValue: true)

关于ios - 仅从存在用户 UID 的节点获取特定的子值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44315214/

相关文章:

objective-c - 访问存储在 iOS 设备上的文本文件

ios - 使用 PFQuery 的 containsAllObjectsInArray 导致错误

ios - App Delegate的应用程序:didReceiveLocalNotification: not called

ios - 无后端轻松 Facebook 登录 : fetching first name

ios - 为什么 Flutter 手机身份验证在我的真实设备上不起作用

iphone - 如何在 iOS 中用渐变填充用 CGPoints 定义的形状?

ios - 如何使用自定义设计显示一串数字?

javascript - Firebase 类型错误的云函数 - 无法读取属性

android - 使用 Firebase 实时数据库时如何将用户从非授权转换为授权的最佳方法

ios - 使用 AVCaptureMovieFileOutput 保存视频后不播放音频