1

My database has values sorted like this :

 Users
    UID
      Username
      Email

I'm wanting to implement a friend adding system where you search for either a username or email and it lets you add the person.

I'm able to locate users by using

 REF_USERS.queryOrdered(byChild: "displayname").queryEqual(toValue: input).observeSingleEvent(of: .value) { (snapshot: FIRDataSnapshot) in {
 print(snapshot.value)
}

With that I get the user's entire dictionary, but I'm having an issue grabbing the UID.

snapshot.key gives me "Users".

How can I grab the UID value out of the dictionary after finding the user's dictionary with either their username/email?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
user6820041
  • 1,213
  • 2
  • 13
  • 29

2 Answers2

2

Try this...

Assume a structure (this is Swift 2, Firebase 2)

users
  uid_0
    email: "someuser@thing.com"
    displayName: "some display name"

and we want to get uid_0's info

let displayName = "some display name"

usersRef.queryOrdered(byChild: "displayName").queryEqual(toValue: displayName)
              .observeSingleEvent(of: .childAdded) { (snapshot: FIRDataSnapshot) in {

     let dict = snapshot?.value as! [String: AnyObject]
     let email = dict["email"]
     let displayName = dict["displayName"]
     print(email!)
     print(displayName!)

     let key = snapshot?.key
     print(key!)
}

A couple things to note

The 'dict' variable is being told it's being assigned a dictionary of type [String: Anyobject].

Any Object could well, be any object. A String, another dictionary, an int. So you need to ensure you code can handle whatever the object is

The snapshot key in this case is the snapshot of this user, and the key must be the parent node, which in this case is uid_0. So the output is

someuser@thing.com
some display name
uid_0

EDIT:

Updated for Firebase 4, Swift 4 and handle the case where multiple children are returned

let usersRef = self.ref.child("users")

let input = "some display name"
let query = usersRef.queryOrdered(byChild: "displayName").queryEqual(toValue: input)
query.observeSingleEvent(of: .value, with: { snapshot in
    for child in snapshot.children {
        let snap = child as! DataSnapshot
        let dict = snap.value as! [String: Any]
        let email = dict["email"] as! String
        let displayName = dict["displayName"] as! String
        print(email)
        print(displayName)

        let key = snapshot.key
        print(key)
    }
})
Jay
  • 34,438
  • 18
  • 52
  • 81
  • This doesn't work. That's fine if you have a single record. How would you find it if you had uid_0 and uid_1 and the email you're looking for is in uid_1. The uid's are auto generated and so you don't know them but need to search the children to find the email and return the record – justdan0227 Feb 06 '18 at 15:10
  • @justdan0227 It does work! Code is tested. However, you're *use case* is different that what was in the question. The OP is asking how to get the UID once the node is found, and my code addresses how to get that UID (which is the snapshot?.key) assuming each node has a discreet userName and email. My code does that. However, if there are a multiple results possible, then the query will return a Snapshot which contains all matching nodes. You would then iterate over the snapshot to get the uid's in question - see Frank's answer for that example. – Jay Feb 06 '18 at 18:40
  • Sorry @Jay, I thought the original question was "How can I grab the UID value out of the dictionary after finding the user's dictionary with either their username/email?" Meaning that you have to first find the "record" based on username/email, and then return the UID. – justdan0227 Feb 06 '18 at 22:09
  • 1
    @justdan0227 Well, good catch - had a typo in the answer! I initially assume the OP was going to return just one user per call but in your case that wouldn't work as there would be multiple results. That's been fixed and also keep in mind that answer was from a couple of years ago with Swift 2 and Firebase 2. I've added the code for Swift 4, Firebase 4 *and* to handle situations where multiple children are returned. – Jay Feb 06 '18 at 23:39
1

When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.

let query = REF_USERS.queryOrdered(byChild: "displayname").queryEqual(toValue: input)
query.observeSingleEvent(of: .value) { (snapshot: FIRDataSnapshot) in {
    for child in snapshot.children {
        print(child.key)
    }
}

Also see:

Community
  • 1
  • 1
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807