what's the best way to implement unique display name in firebase?

8,301 views
Skip to first unread message

Herman Chan

unread,
Dec 24, 2014, 11:54:24 AM12/24/14
to fireba...@googlegroups.com
hi there,

I am currently storing user information like the following in firebase.

  1. {
  2. "users": {
  3. "login:1": {
  4. "displayName": "alanisawesome",
  5. "provider": "password",
  6. "provider_id": "1"
  7. },
  8. "login:2": {
  9. "displayName": "gracehop",
  10. "provider": "password",
  11. "provider_id": "2"
  12. }
  13. }
  14. }

I could like to make displayName unique when user sign up to our service, what's the best way to do that in Firebase?

Herman

Kato Richardson

unread,
Dec 24, 2014, 12:09:13 PM12/24/14
to fireba...@googlegroups.com
Herman,

"The best way" is highly dependent on the specifics of your use case. Can you elaborate?

Cheers,
Kato


--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/986791b5-b33d-4211-9793-5d185056c4aa%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Herman Chan

unread,
Dec 24, 2014, 12:13:18 PM12/24/14
to fireba...@googlegroups.com
Hi Michael,

Well, we have a sign up form for our user to sign up with email/password and they can give us a displayName.  We want to keep the displayName to be unique across all users, so before storing the user provided, we'll like to check if the same displayName is in our system already.

We are thinking to have a extra tree in Firebase like "/displayNames/xxx" and simply check for existence there, but that'll mean we'll have to keep the displayName in sync between the "/users" tree and the "/displayNames" tree when the user decided to change the displayName.

Let me know if this isn't clear enough.

Thanks,
Herman

Jacob Wenger

unread,
Dec 26, 2014, 10:32:30 AM12/26/14
to fireba...@googlegroups.com
Hey Herman,

I am re-creating this answer from this previous Google Group question. Look there for more details.

Typically when dealing with an app with user authentication, I suggest that they create a /users/ node at the root of their Firebase. This node will have children which are the uid values of the users returned from Firebase Simple Login. You should use uid because it is unique across all users on all providers, not just across one provider as is the case with id. Every time a user logs in, you would check if /users/$uid/ exists, where $uid is the logged-in user's uid. If it doesn't create a new node there and put in whatever information you want (first name, last name, email, login provider, username, path to profile picture, etc.). If the node already exists, then just retrieve all of the user's information from it. Since we can store their username in their particular node, we can easily retrieve it after they log in.

You could then have security rules which look something like this:

{
  "rules": {
    "users": {
      "$uid": {
         ".read": "auth != null && auth.uid == $uid",
         ".write": "auth != null && auth.uid == $uid",
         ".validate": "newData.hasChildren('displayName', 'provider', 'provider_id')"
      }
    }
  }
}

Since you want to ensure everyone has a unique username, you could do two things. You could go with my suggestion above and when a new user logs in, ask them for a username and loop through each child in the /users/ node (using a child_added event on the /users/ node). For each child, see if the username selected already exists. This obviously won't scale well as your app grows but would certainly work.

A better solution for you may be to use your unique username as the /users/ node's child keys instead of the uid values. Then, when a new user tries picking a username (say "jacob"), you can use a Firebase query to check if the username is taken:

usersRef.startAt(null, "jacob").endAt(null, "jacob").on("value", function(snapshot) {
  if (snapshot.val() === null) {
    // username not taken
  } else {
    // username taken
  }  
});

Hope that helps!

Jacob

Herman Chan

unread,
Dec 29, 2014, 3:19:52 PM12/29/14
to fireba...@googlegroups.com
Hi Jacob,

Thanks for the response.

The second solution you have is great for user name uniqueness but we'll have to actually reference the user  in some other node as well.  For example, a cart node will have a property with user in it.  With the second solution, the user property will be the userName (since this is the key of a user), this would work until the user decided to change their user name, whenever a user change their name, we'll have to go through every single node in firebase and find the old user property and update it, which is not very scalable.  

We could put in the uid in the user property of the cart node, but I don't know if there is a efficient way to look up a userName for display with the schema suggested.

Thanks for you help again,
Herman

Jacob Wenger

unread,
Jan 4, 2015, 5:37:58 PM1/4/15
to fireba...@googlegroups.com
Hey Herman,

I think the issue you mentioned is the tradeoff you are making by keying your users by something which can be changed (that is, the username). That is why we suggest using (and all our examples use) the uid we generate as the unique key for users and I would suggest using the first option I provided. I think it is easiest in the longterm.

That being said, if you want to use the second option, you should most definitely still use the uid instead of the username when joining your Firebase data. Then, if you need to look up user from a uid, you can do a query on the uid. This requires you to store the uid for every user in your /users/ node, which I assume you are already doing. Here is the query to get a user object given some uid:

usersRef.orderBy("uid").startAt(uid).endAt(uid).on("value", function(snapshot) {
  var user = snapshot.val();
});

Hopefully that clears things up,
Jacob

Reply all
Reply to author
Forward
0 new messages