Swift Firebase -.queryStarting(atValue:) and .queryEnding(atValue:) returning all children

时间:2019-04-08 13:47:00

标签: ios swift firebase firebase-realtime-database

When I query a specific child I get all the results back instead of the ones specific to what I'm looking for:

For eg if my search text begins with the letter "c" I should only get the cat and the cow from below but for some reason I'm also getting the bull.

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

I was thinking maybe the issue is because I seem to grab everything at the users node (dictionaries plural) and then loop through the dictionaries that might be the issue but then I realized it should still only be the username values beginning with the letter "c" that should appear inside the dictionaries to begin with and bull should get skipped.

Where am I going wrong at?

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()
        }
})

Updated with Json per Frank's request:

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

A picture to match. I excluded the other 2 objects from the json because even though they showed up on my end (I actually got 5 results) I wanted to just focus on what's in the question which is the first 3.

enter image description here

2 个答案:

答案 0 :(得分:0)

我刚刚尝试了这段代码:

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

上面的数据结构正是我所期望的。

答案 1 :(得分:0)

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

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

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

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

为解决此问题,我删除了实例ref初始化

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

,而是将查询所需的所有内容链接到Database对象本身,并且一切正常。

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

仅有的2个结果是猫和牛。非常奇怪的错误

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()
        }
})