Abdullah Ajmal
Abdullah Ajmal

Reputation: 463

How to exclude a specific userID (user) from the database in Firebase with Swift

I am working on the user profile page of my app, where the user can make changes to the user info, like change their username, name... Each user has their own unique username, I have done that with the following code:

// Function to check if the username is taken
static func checkUsernameUnique(newUserName: String, completion: @escaping(Bool) -> Void) {

    let ref = Database.database().reference()
    ref.child("Users").queryOrdered(byChild: "Username").queryEqual(toValue: newUserName).observeSingleEvent(of: .value, with: {(snapshot: DataSnapshot) in
        if snapshot.exists() {
            completion(true)
        } else {
            completion(false)
        }
    })
}

This checks if there is a user with the same username. Calling this function:

checkUsernameUnique(newUserName: username) { isExist in
    if isExist {
        print("Username is taken")

    } else {
        print("Username is not taken")

    }
}

The problem with this is that this checks if there is a user using the same username with all the other users in the database, including the current user. How do I exclude the current user?

My database

Code that I tried with the help of one of the answers

static func checkUsernameUnique(newUserName: String, completion: @escaping(Bool) -> Void) {

    let ref = Database.database().reference()

    if let userID = Auth.auth().currentUser?.uid {

        print(userID)
        ref.child("Users").queryOrdered(byChild: "Username").queryEqual(toValue: newUserName).observeSingleEvent(of: .value, with: {(snapshot: DataSnapshot) in

            if !snapshot.exists() {
                completion(false)

            } else {


                //Here we will check the given user's UID
                snapshot.ref.child("UserID").observeSingleEvent(of: .value, with: { (uidSnapshot) in
                    //This forced cast should never fail
                    let uid = uidSnapshot.value as! String
                    print(uid)
                    //Now we use FirebaseAuth to cross reference the current user's UID with whatever the "Username" node's sibling node "UserID" is
                    if Auth.auth().currentUser!.uid == uid {
                        //The returned user is the same as the current user
                        completion(false)
                    } else {
                        //The returned user is not the same as the current user
                        completion(true)
                    }
                })

            }
        })

    } else {

        ref.child("Users").queryOrdered(byChild: "Username").queryEqual(toValue: newUserName).observeSingleEvent(of: .value, with: {(snapshot: DataSnapshot) in
            if snapshot.exists() {
                completion(true)
            } else {
                completion(false)
            }
        })
    }
}

Upvotes: 0

Views: 403

Answers (2)

David Chopin
David Chopin

Reputation: 3064

Try this. All we have to do is get the userID of whatever is returned from the query, and check if it equals the current user's uid.

// Function to check if the username is taken
static func checkUsernameUnique(newUserName: String, completion: @escaping(Bool) -> Void) {

    let ref = Database.database().reference()
    ref.child("Users").queryOrdered(byChild: "Username").queryEqual(toValue: newUserName).observeSingleEvent(of: .value, with: {(snapshot: DataSnapshot) in

        guard let json = snapshot.value as? [String:[String:Any]] else {
            completion(false)
            return
        }

        //Assuming there will never be more than one database entry with this username, this first element (result) can be unwrapped explicitly without crashing
        let result = json.first!.value

        let userID = result["UserID"] as! String

        if Auth.auth().currentUser!.uid == uid {
            completion(false)
        } else {
            completion(true)
        }
    })
}

Upvotes: 1

Doug Stevenson
Doug Stevenson

Reputation: 317750

There is no way to conditionally exclude data from a query. You will have to check in your client code if specific data is present in the result, and exclude it from there. Just checking snapshot.exists will not be sufficient in your case - instead, look inside the snapshot to see if it contains the UID of the current user.

Upvotes: 1

Related Questions