KingTim
KingTim

Reputation: 1301

How to check a firebase subnode for a specific value (UID)?

I'm trying to query Firebase to check if the current user's uid is listed in a room's "participants". If so, I grab the info for that room.

Below is my current observer which listens to ALL rooms in the app, not just the rooms the user is a participant of. But I need to perform a check first, to see which rooms the current user's UID is listed in; if there's a match (the uid is in a room's participants), THEN get the data for that room:

private func observeRooms() {

    guard let uid = FIRAuth.auth()?.currentUser?.uid else {print("Error getting user UID"); return}

    roomRefHandle = roomRef.observe(.childAdded, with: { (snapshot) -> Void in

        let roomData = snapshot.value as! Dictionary<String, AnyObject>
        let id = snapshot.key
        guard let name = roomData["roomName"] as! String! else {print("Error getting user name"); return}

        self.usersRooms.append(Room(id: id, name: name, participants: [uid]))

        self.tableView.reloadData()
    })
}

This is how the rooms are structured in the database:

"rooms" : {
    "-Ki6TJWO-2R1L4SyhSqn" : {
      "messages" : {
        "-Ki6TWrXxWqjaRJAbyVt" : {
          "senderId" : "tzfHgGKWLEPzPU9GvkO4XE1QKy53",
          "senderName" : "Timothy",
          "text" : "Room One message"
        }
      },
      "participants" : {
        "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true
      },
      "roomName" : "Room One"
    },
    "-Ki6TKOnmToeUuBzrnbb" : {
      "participants" : {
        "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true
      },
      "roomName" : "Room Two"
    },
    "-Ki6TLGC1Encm1v-CbHB" : {
      "participants" : {
        "tzfHgGKWLEPzPU9GvkO4XE1QKy53" : true
      },
      "roomName" : "Room Three"
    }
   }

How can I change my function so that it first checks all the room's participants for the current user's uid, before grabbing the values?

Thanks for any suggestions!

EDIT: Jay's approach:

private func observeRooms() {

    guard let uid = FIRAuth.auth()?.currentUser?.uid else {print("Error getting user UID"); return}
    let queryRef = roomRef.queryOrdered(byChild: "participants/\(uid)").queryEqual(toValue: true)

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

        let roomDict = snapshot.value as! [String: AnyObject]

        let id = snapshot.key

        let roomName = roomDict["roomName"] as! String
        let participants = roomDict["participants"] as! [String: AnyObject]
        let numberOfParticipants = participants.count

        print("\nRoom Name: \(roomName)")
        print("Participants: \(participants)")
        print("Room ID: \(id)\n")

        self.usersRooms.append(Room(id: id, name: roomName, participants: [uid]))
        self.tableView.reloadData()
    })
}

Upvotes: 1

Views: 488

Answers (2)

Jay
Jay

Reputation: 35657

To keep it super simple, store a reference to the user in each room they belong to.

rooms
  room_0
   room_name: "My Room"
   users
    user_1: true
    user_2: true
  room_1
   room_name: "Their Room"
   users
    user_1: true

Then a simple query which will gather all the needed data, and will also leave an observer attached so if this user joins any new rooms the app will be notified.

let roomsUsersRef = self.ref.child("rooms")
let queryRef = roomsUsersRef.queryOrdered(byChild: "users/user_1").queryEqual(toValue: true)

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

    let roomDict = snapshot.value as! [String: AnyObject]
    let roomName = roomDict["room_name"] as! String

    let usersDict = roomDict["users"] as! [String: AnyObject]
    let userCount = usersDict.count

    print("Room: \(roomName) has \(userCount) users")
})

and the output

Room: My Room has 2 users
Room: Their Room has 1 users

You could expand on this with .childChanged and .childRemoved to keep track of any events that occur in a room this user belongs to. So if another user joins or leaves a room this user is in, app will be notified; if the owner of the room boots this user from the room, the app will also be notified.

Upvotes: 2

Mathew Berg
Mathew Berg

Reputation: 28750

Ideally you would create a separate node in your app to store the information you want. Something like:

{
    "usersRooms": {
        "tzfHgGKWLEPzPU9GvkO4XE1QKy53": {
            "-Ki6TJWO-2R1L4SyhSqn": true,
            "-Ki6TKOnmToeUuBzrnbb": true,
            "-Ki6TLGC1Encm1v-CbHB": true
        }
    }
}

This would allow you to get the node for the user and instantly see what rooms they are apart of. Once you've done that you can loop over the results to get the individual rooms. In terms of keeping this list updated look into firebase functions or roll your own.

Upvotes: -1

Related Questions