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

时间:2017-06-01 19:03:15

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

我正在开发群聊应用程序,但我在尝试向Firebase数据库发出特定查询时遇到了麻烦。

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

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没有显示在数据库中。

这就是我将节点添加到" groups"在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所参与的群组?

1 个答案:

答案 0 :(得分:1)

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

有几种方法可以解决这个问题,需要努力。

首先,您可以利用sort order只获得那些拥有某个对象且具有UID名称的人。由于Firebase首先排序空,然后是基元,最后是对象,您应该能够按子顺序排序, 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(以及组ID,如果您要在用户上查询)将具有true的值,以便您可以再次使用简单的值查询。

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

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

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