【问题标题】:Swift Firebase -.queryStarting(atValue:) and .queryEnding(atValue:) returning all childrenSwift Firebase -.queryStarting(atValue:) 和 .queryEnding(atValue:) 返回所有孩子
【发布时间】:2019-04-09 06:48:27
【问题描述】:

当我查询特定孩子时,我会返回所有结果,而不是特定于我正在寻找的结果:

例如,如果我的搜索文本以字母“c”开头,我应该只从下面得到猫和牛,但由于某种原因,我也得到了公牛。

root
  |
  @---users
        |
        @---uid_1000
        |    |--uid: "uid_1000"
        |    |--username: "bull"
        |
        @---uid_2000
        |    |--uid: "uid_2000"
        |    |--username: "cat"
        |
        @---uid_3000
             |--uid: "uid_3000"
             |--username: "cow"

我在想问题可能是因为我似乎在用户节点(字典复数)上抓取了所有内容,然后遍历可能是问题的字典,但后来我意识到它应该仍然只是用户名值以开头应该出现在字典中开头的字母“c”,而公牛应该被跳过。

我哪里出错了?

let searchText = "c"

let ref = Database.database().reference().child("users")
    .queryOrdered(byChild: "username")
    .queryStarting(atValue: searchText)
    .queryEnding(atValue: searchText + "\u{f8ff}")

ref?.observeSingleEvent(of: .value, with: { (snapshot) in

    if !snapshot.exists() { return }

    // dictionaries plural
    guard let dictionaries = snapshot.value as? [String: Any] else { return }

    dictionaries.forEach({ (key, value) in

        guard let dict = value as? [String: Any] else { return }
        let user = User(dict: dict)

        let isContained = self.users.contains(where: { (containedUser) -> Bool in
            return user.uid == containedUser.uid
        })

        if !isContained {
            self.users.append(user)
            self.collectionView.reloadData()
        }
})

根据 Frank 的要求更新了 Json:

{
  "users" : {
    "1000" : {
      "userId" : "1000",
      "username" : "bull"
    },
    "2000" : {
      "userId" : "2000",
      "username" : "cat"
    },
    "3000" : {
      "userId" : "3000",
      "username" : "cow"
    }
  }
}

要匹配的图片。我从 json 中排除了其他 2 个对象,因为即使它们出现在我的最后(我实际上得到了 5 个结果),我只想专注于问题中的前 3 个。

【问题讨论】:

  • 据我所知,您在代码中添加了正确的过滤器,并且应该只获取其username 属性以c 开头的子节点。你可以试试这个简化版:let ref = Database.database().reference().child("users") .queryOrdered(byChild: "username") .queryStarting(atValue: "c") .queryEnding(atValue: "d")
  • 我刚试了你的简化版,同样的事情发生了,三个都被退回了。
  • 以下是我的规则,如果它有什么不同的话: "users": { ".read": "auth.uid != null", ".indexOn": ["username"], "$ uid": { ".write": "$uid === auth.uid" }
  • 规则只决定是否返回结果,而不是what返回结果。您可以发布文字 JSON(作为文本,没有屏幕截图),所以我可以试一试?您可以通过单击Firebase Database console 上溢出菜单 (⠇) 中的“导出 JSON”链接来获取此信息。
  • 您需要来自所有其他节点的所有数据吗?我有 19 个具有不同信息的节点。除非你真的需要,否则会很混乱

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

我刚试过这段代码:

let ref = Database.database().reference(withPath: "55574954")
ref.child("users") .queryOrdered(byChild: "username") .queryStarting(atValue: "c") .queryEnding(atValue: "d").observeSingleEvent(of: .value, with: { (snapshot) in
    for child in (snapshot.children.allObjects as! [DataSnapshot]) {
        print(child.key)
    }
})

关于这个数据结构:

{
  "users" : {
    "1000" : {
      "userId" : "1000",
      "username" : "bull"
    },
    "2000" : {
      "userId" : "2000",
      "username" : "cat"
    },
    "3000" : {
      "userId" : "3000",
      "username" : "cow"
    }
  }
}

实时 JSON 为 here

运行此代码打印:

2000

3000

这正是我对上述数据结构的期望。

【讨论】:

  • 您好,感谢您的尝试。我不知道到底发生了什么。我在完全不同的节点上使用代码,它工作正常,所以也许我的 vc 中有什么东西导致了错误。一旦确定,我会继续寻找并回复您。再次感谢你的帮助!顺便说一句,我有 1 个问题(也许我最好将其作为新问题提交)。使用 obsereSingleEvent 然后遍历字典是否正确?如果有一百万个用户名以“c”开头的节点,那就是大量的客户端过滤
  • 如果您在users 上定义索引,则过滤在服务器端完成。但是,您可以合理拥有的节点数量限制。看看stackoverflow.com/questions/39712833/…。除此之外,还可以考虑分片,例如:根据第一个字符将名称放在子节点中。
  • 好的,再次感谢,我会查看并回复您有关此问题已解决的问题。干杯!
  • 我发现了问题,真的很奇怪。我有一个名为blockedRef 的类属性,在viewWillAppear 中我用.observe(.value) 对其进行了初始化。这个 ref 与我的用户 ref 没有任何联系,我只是在那里检查以确保该用户没有被任何人阻止。不知何故,blockedRef 破坏了我对用户 ref 的查询。我也仍然有问题。奇怪的东西?
  • 这是我们要求 MCVE 的原因之一,因为我们不可能在您的应用中看到这种类型的交互。这也是我提供 MCVE 的原因,它显示了最适合我的代码+数据。
【解决方案2】:

我不确定为什么会这样,但这是一个非常奇怪的错误。

我没有在我的问题中添加的第一件事是我在与我用于查询的类相同的类中有另一个观察者。

我有一个名为blockedRef 的类属性,在viewWillAppear 中我用.observe(.value) 对其进行了初始化。这个 ref 与我的用户 ref 没有任何联系,我只是在那里检查以确保该用户没有被任何人阻止。不知何故,blockedRef 破坏了我对用户 ref 的查询。

一旦我删除了被阻塞的Ref观察者 1 问题就解决了(在我的实际项目中,我最初得到 5 个结果,然后删除后我得到 3 个结果,但它们仍然不正确)。

为了解决这个问题,我删除了实例引用初始化

let ref = Database.database().reference().child("users")....

而是将查询所需的一切链接到数据库对象本身,一切正常。

Database.database().reference().child("users")
    .queryOrdered(byChild: "username")
    .queryStarting(atValue: searchText)
    .queryEnding(atValue: searchText + "\u{f8ff}")
    .observeSingleEvent(of: .value, with: { ...

显示的仅有 2 个结果是 cat 和 cow。很奇怪的bug

let searchText = "c"

Database.database().reference().child("users")
    .queryOrdered(byChild: "username")
    .queryStarting(atValue: searchText)
    .queryEnding(atValue: searchText + "\u{f8ff}")
    .observeSingleEvent(of: .value, with: { (snapshot) in

    if !snapshot.exists() { return }

    // dictionaries plural
    guard let dictionaries = snapshot.value as? [String: Any] else { return }

    dictionaries.forEach({ (key, value) in

        guard let dict = value as? [String: Any] else { return }
        let user = User(dict: dict)

        let isContained = self.users.contains(where: { (containedUser) -> Bool in
            return user.uid == containedUser.uid
        })

        if !isContained {
            self.users.append(user)
            self.collectionView.reloadData()
        }
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多