1

I have to get a user's id by providing its email. My structure is:

users
    -Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2
        -email: "batuarslan@gmail.com"
        -lists
            slid: "-LJsrWDfMPNcs_NjVYBM"
            uid:  "Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2"

Is there a way to do this? Or do I have to restructure my tree in another way? My code:

func userLookUpByEmail (email: String, completionHandler: @escaping (_ result: String) -> Void) {
    var userId : String = ""

    usersRef.queryOrdered(byChild: "email").queryEqual(toValue: email).observeSingleEvent(of: .value, with: { snapshot in
        if snapshot.value != nil {
            userId = snapshot.key
        }
        else {
            userId = "nil"
        }
        completionHandler(userId)
    })
}

func userLookUpByEmail (email: String, completionHandler: @escaping (_ result: String) -> Void) {
    var userId : String = ""

    usersRef.queryOrdered(byChild: "email")
            .queryEqual(toValue: email)
            .observeSingleEvent(of: .value, with: { snapshot in

        if snapshot.value != nil {
            userId = snapshot.key
        }
        else {
            userId = "nil"
        }
        completionHandler(userId)
        })
    }
  • What's wrong with the code you posted here? – André Kool Aug 14 '18 at 14:55
  • Sorry I forgot to add the function. This function queries for email but email is under uid. Therefore, without knowing what the uid is, I cant really check for the email. –  Aug 14 '18 at 15:00

1 Answers1

0

Firebase database structure documentation suggests to have a flat structure with two directional entries that can add redundancies to fasten the lookup.

Refer the link "Create data that scales" from https://firebase.google.com/docs/database/ios/structure-data

For scaling the efficient way one should adding two way entries analogous to " foreign keys in SQL" along with the indexing.

For example, in your case: There is nothing wrong with what you are trying to do in the code you have shown. But in order to scale it add a new node emailhashes(as emails cannot be used as nodes/subnodes) preferably sibling to your users node. This emailhashes node should store mapping of emailhash to uid.

users
-Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2
    -email: "batuarslan@gmail.com"
    -lists
        slid: "-LJsrWDfMPNcs_NjVYBM"
        uid:  "Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2"
 ...
 ...

 ...
emails
 -<md5 hash of "batuarslan@gmail.com">: "Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2"
...
...

...

So, lookupByEmail should first generate the md5 hash for the input email and lookup the emailhash in emailhashes node to get corresponding uid and then by using lookupByUID you can get the userdata.

For generating md5 hash of the email, please refer: How to convert string to MD5 hash using ios swift

Indexing on firebase real-time database is done by applying database rules. Please refer:

https://firebase.google.com/docs/database/security/indexing-data

Ketan Yekale
  • 2,108
  • 3
  • 26
  • 33
  • I tried this but apparently we cant put emails as keys. Keys cannot be nil, empty or include some chars such as ".". I also tried replacing "." with ","(it works) but that seemed like a hack and not really a clean way of doing it. –  Aug 14 '18 at 15:53
  • Oops I totally forgot that. Instead of using the email as keys, we can use email hashes as keys. To get md5 hash you can refer: https://stackoverflow.com/questions/32163848/how-to-convert-string-to-md5-hash-using-ios-swift. I'll update the answer accordingly. – Ketan Yekale Aug 14 '18 at 16:17