2

I have the following JSON structure in my Firebase Database:

- users
    |
    +--- key: 123 
    |     |
    |     +-----name : Tom
    |     +-----email: tom@mymail.com
    |
    +--- key: 456 
          |
          +-----name : Peter
          +-----email: peter@othermail.com

Now I want to check if any user with the email tom@mymail.com exists or not.

I thought:

DatabaseReference usersRef = db.getReference("users");
usersRef.orderByChild("email")
        .equalTo("tom@mymail.com")
        .addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        //fires if exists
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {                            
    }
});

But this only fires if a user exists and not if it doesn't. How to do it properly?

juergen d
  • 201,996
  • 37
  • 293
  • 362
  • See these answers: https://stackoverflow.com/questions/35243492/firebase-android-make-username-unique https://stackoverflow.com/questions/39149216/firebase-security-rules-to-check-unique-value-of-a-child-askfirebase – Jen Person Aug 31 '17 at 21:06

2 Answers2

2

You can use exactly the code you provided. It will fire no matter if it exists or not. You only need to check if the data exists in the onDataChange() method:

DatabaseReference usersRef = db.getReference("users");
usersRef.orderByChild("email")
        .equalTo("tom@mymail.com")
        .addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(dataSnapshot.exists()) {
           //exists!
        }
        else {
           //does not exist
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {                            
    }
});

I thought this does not work and I could swear I tried it (maybe with an earlier version of Firebase) but it works!

juergen d
  • 201,996
  • 37
  • 293
  • 362
1

I see two ways of approaching this:

  1. Load the entire list of users and process it on the device (Not recommended if you have a huge number of users, which you probably do). I will not post the code here because I'm affraid beginners will simply copy and paste it and write awful apps...
  2. Create a node containing the emails of users registered (let's call it userEmails):

    userEmails { "tom@mymail.com":true, "peter@othermail.com": true }

Now, in order to check if the user exists or not:

usersRef.child("tom@mymail.com").addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                if(dataSnapshot.exists()) {
                                    //User exists
                                }
                                else
                                {
                                    //User doesn't exist
                                }
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {}
                        });

The downside of this is that you will have to insert data into both nodes when a new user is registered.

  • 1
    Another challenge of this method is that keys cannot have periods in them. If you store emails as keys, you will need to replace the period with a different character. – Jen Person Aug 31 '17 at 20:41
  • 1
    @JenPerson Idiomatically we use a `,` as the replacement for `.` in that case, since -conveniently- email addresses cannot contain `,`. :-) – Frank van Puffelen Sep 01 '17 at 02:37