1

I'm trying to understand where i may be going wrong with the following code. I have tried to look up a way to check if the users collection contains a string within one of it's documents within a username field.

Structure looks something like this

#users(collection)
    #userID(document)
        #name:String
        #email:String
        #username:String
    #userID(document)
        #name:String
        #email:String
        #username:String

What i am trying to check is if within users, and within any document, does the string exist in the username field. Found a possible solution to this question (among others) here by calling a function to query for the username.

I created the function in an extension:

extension UITextField {

    func checkUsername(username: String, completion: @escaping(Bool) -> Void) {
        let usernameRef = Database.database().reference()
        usernameRef.child("users").queryOrdered(byChild: "username").queryEqual(toValue: username).observeSingleEvent(of: DataEventType.value, with: { (snapshot: DataSnapshot) in
            if snapshot.exists() {
                completion(true)
            }
            else {
                completion(false)
            }
        })
    }

}

and called it on the text field within textFieldDidEndEditing so it can perform the check upon the user attempting to claim a username.

func textFieldDidEndEditing(_ textField: UITextField) {

    if activeField == usernameField {
        textField.checkUsername(username: usernameField.text!) { isExist in
            if isExist {
                print("Username exists")
            } else {
                print("Username does not exist")
            }
        }
    }

}

However, this always returns 'Username does not exist' to the console, even when the username does exist.

There is currently 1 username within the database called test, so attempting to enter test should return 'Username exists' and entering testtwo should return 'Username does not exist'.

What can i be missing here? I am assuming its not querying the database correctly?

Jason
  • 209
  • 2
  • 13
  • You tagged the question as Cloud Firestore, but are using the Firebase Realtime Database in your code. The two databases are quite different, so which one are you using? – Frank van Puffelen Jul 14 '18 at 00:21
  • Firestore :) I assume that's where it's going wrong if i am attempting to check a realtime database instead of Firestore database. – Jason Jul 14 '18 at 00:36
  • 1
    Yeah, that definitely won't work. Be sure to check the Firestore documentation on getting documents, here: https://firebase.google.com/docs/firestore/query-data/get-data – Frank van Puffelen Jul 14 '18 at 00:39
  • Thanks! Just taking a look now to see what i need to amend? On that note, would it better to place all the usernames into a separate collection called 'usernames' when the user is created, so i would only need to query the documents in the collection, rather than query each document individually for a field which has the username? – Jason Jul 14 '18 at 00:48
  • 1
    Performance wise that would be pretty much the same, so I'd go for the simplest solution. – Frank van Puffelen Jul 14 '18 at 04:19

1 Answers1

4

Thanks to Frank for pointing out i was calling the Realtime Database rather than Firestore. Updated my code to return a true or false value when checking documents for anything stored within 'username' and thought i would share my updated code if anyone else is attempting to check 'usernames' within their Firestore DB.

Created an extension on the UITextField which is called when i require checking a username is available:

func checkUsername(field: String, completion: @escaping (Bool) -> Void) {
    let collectionRef = db.collection("users")
    collectionRef.whereField("username", isEqualTo: field).getDocuments { (snapshot, err) in
        if let err = err {
            print("Error getting document: \(err)")
        } else if (snapshot?.isEmpty)! {
            completion(false)
        } else {
            for document in (snapshot?.documents)! {
                if document.data()["username"] != nil {
                    completion(true)
                }
            }
        }
    }
}

Then on the UITextField textDidEndEditing, i call the function is the active field is the username field:

func textFieldDidEndEditing(_ textField: UITextField) {

    if activeField == usernameField {
        if textField.text?.isEmpty == false {
            textField.checkUsername(field: textField.text!) { (success) in
                if success == true {
                    print("Username is taken")
                    // Perform some action
                } else {
                    print("Username is not taken")
                    // Perform some action
                }
            }
        }
    }

} 

This then returns 'Username is taken' if i attempt to enter a username that exists in any of the documents username field, or 'Username is not taken' if nothing is found.

If anyone has any feedback to improve the code or any questions, let me know. I'll happily update for reference. :)

Jason
  • 209
  • 2
  • 13