Firebase queryOrdered、queryEqual 不适用于在比孙子更深的节点上进行排序和查找

问题描述 投票:0回答:1

我查看了几篇 StackOverflow 帖子,了解如何通过对几个节点深的子值进行相等来获取数据值。

Firebase 数据库中 - 如何执行前缀通配符查询 数据库结构为:

并且查询

ref.child("user_id").orderByChild("name").equalTo("objective-c")
可以提取具有特定uid的子项。

Firebase按子值搜索中,数据库结构为:

并且查询

ref.child('users').orderByChild('name').equalTo('John Doe')
能够找出合适的孩子。

在这两种情况下,排序和相等都是由孙子完成的。然而,就我而言,数据库结构有点不同。我想按几层深的子属性进行索引。其结构为:

所以我尝试运行以下查询:

authenticatedUsersReference.queryOrdered(byChild: fcmTokenKey).queryEqual(toValue: fcmToken).observeSingleEvent(of: .value)
,我的快照返回
nil
。但是当我运行
 authenticatedUsersReference.queryOrdered(byChild: fcmTokenKey).observe(.value)
时,我看到快照值是按 fcmToken 排序的。
authenticatedUsersReference
指向
Database.database().reference().child("people/authenticated")
。我还更新了我的规则以在服务器端建立索引。据我所知,即使深度发生变化,这个概念也应该保持不变,那么我错过了什么导致我的查询返回
nil

"people": {
      "users": {
        "authenticated": {
          "$userName": {
            ".indexOn": ["fcmToken"]
          }
        }
      }
    }
swift firebase firebase-realtime-database indexing
1个回答
1
投票

您正在

$userName
上为
fcmToken
定义索引。这允许您查询特定
$userName
节点的
fcmToken
属性。

但是您的代码会查询所有用户的

fcmToken
属性,而该属性不存在索引。因此,第一个修复是您需要在要查询的位置上定义索引,依此类推
authenticated
:

"people": {
  "users": {
    "authenticated": {
      ".indexOn": ["fcmToken"]
    }
  }
}

现在上面在正确的位置创建了索引,所以让我们看看它在索引中放入了什么值。

对于

authenticated
的每个子节点,上面获取其
fcmToken
属性并将该属性的值放入索引中。但是如果我们查看您的 JSON,
authenticated
的子节点没有 direct 子属性
fcmToken
。因此,索引中没有任何值可放入,这解释了为什么您没有得到查询结果。

相反,您在(固定)路径有一个子属性:

stats/fcmToken
,所以这也是您应该在索引定义中使用的。

总共:

"people": {
  "users": {
    "authenticated": {
      ".indexOn": ["stats/fcmToken"]
    }
  }
}

根据该定义,索引中存在正确的值,您可以使用以下方式查询它:

authenticatedUsersReference
  .queryOrdered(byChild: "stats/fcmToken")
  .queryEqual(toValue: fcmToken)

编辑:

一旦获得此快照,所有与获取密钥相关的方法都将不再有用,因为根引用是

authenticated/
。所以
snapshot.ref
snapshot.key
都会指向这一点。

大多数此类问题都需要能够获取与检索到的子项关联的 UID。 (例如,如果多个用户的 firToken 相同,则可以是多个)

实现此目的的最小方法,无需使用

JSONDecoder
进行复杂且不必要的解析,如下所示:

{(snapshot) in
    guard let value = snapshot.value as? [String: Any] { return }
    let uids = Array(snapshot.keys)
    print("UIDs for with matching FCMToken are: \(uids)")
    //UIDs for with matching FCMToken are: ["userId", "otherUserId"]
}
© www.soinside.com 2019 - 2024. All rights reserved.