0

In Firebase when searching for a username (or anything search related for that matter) what is the difference between .queryOrdered().queryEqual(toValue: and child().observeSingleEvent(

I looked at the answer and comments below from @Frank van Puffelen

In these comments he says to use:

reference.child("usernames").child(usernameYourSearchingFor).observeSingleEvent(of: .value, with: { (snapshot) in

    if snapshot.exists() { ... } else { ... }
})

But in this answer he answered with:

ref.child("users").queryOrdered(byChild:"username").queryEqual(toValue: usernameYourSearchingFor).observeSingleEvent(of: .value, with: { snapshot in

    if snapshot.exists() { ... } else { ... }
})

When searching the database using either of these methods, is there a difference between speed and efficiency, or is it simply a matter of using 2 different methods to achieve the same exact goal?

Lance Samaria
  • 17,576
  • 18
  • 108
  • 256

1 Answers1

1

Basically, those operations are meant for two different data structures.

In the first one, you'd have a data structure similar to this:

{
  "usernames": {
    "usernameYourSearchingFor": {
      // some data
    },
    "otherUsername": {
      // different data
    }
  }
}

As you can see, the username you're searching for is a key under the "usernames" node. You can access it directly, by calling the child() function. (and then a single event observer is attached to it)


Now in the second structure:

{
  "users": {
    "user1": {
      "username": "usernameYourSearchingFor",
      "email": "user1@email.com"
    },
    "user2": {
      "username": "otherUsername",
      "email": "user2@email.com"
    }
  }
}

The username is actually an attribute belonging to the User object. There's no way you can access it directly, so you need to query the "users" node in order to find the username you're searching for, hence the need of .queryOrdered(byChild:"username").queryEqual(toValue: usernameYourSearchingFor).

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • 1
    @LanceSamaria To clarifiy one thing in this answer; Often times a user is logging in and you need to retrieve data about that user; their username, email and favorite food for example. In those cases, you know the users *uid* from the Auth variable and can in fact directly access their data such as *users/their_uid/username* or *users/their_uid/favFood*. This is also true in a blogging example where the user may have followers - you will know their followers uid's and can access their usernames directly. Bottom line is don't query when you can directly access the data, queries are 'heavier' – Jay Jul 23 '18 at 18:17
  • @Jay thanks for the info. My query concerns are more related to users who download my app, don't log in, and then search for a user name. Those users aren't auth'd in but they still need to access the db. I'm in the process of setting up server tokens to give them temp auth access for searching until they log in but I still wanted to know what was the difference because I've read a lot of SO posts and most people answer towards the second way I posted about instead of the first when searching for usernames. – Lance Samaria Jul 23 '18 at 20:46
  • @LanceSamaria In your use case, go with option 2... Option 1 works but it's generally best practice to disassociate node keys from the data they contain. Things like user names and email addresss can change and if that happens, it a lot of work to go through ALL of the nodes in the database and read the key and children, update the key, re-write the key. It's much easier to change the child node. – Jay Jul 23 '18 at 23:36
  • @Jay good point. The problem I see with the 2nd way is that users are directly accessing other user’s personal nodes to search for a username. Shouldn’t those only be privy the actual owner? Also, wouldn’t the searches take longer since your now searching a couple of levels deeper? – Lance Samaria Jul 23 '18 at 23:56
  • @LanceSamaria Queries are 'heavier' than observing a node as they take more resources and observing a node directly (as in example 1) will be faster and 'more efficient'. That being said, this query is pretty light so I don't think it would have much impact. Firebase is blisteringly fast and and performance difference would probably be imperceptible. As far a security, your statement is correct. However, you've not asked that as part of your question so don't know your use case. It may me a situation where you want to store usernames in a separate node with the key of each being the uid. – Jay Jul 24 '18 at 12:31
  • 1
    @Jay thanks for the help. As with anything pertaining to programming there seems to be multiple ways to achieve searching for a user name. I’m still building out my app and I’ve been able to successfully search both ways but then again it’s in test mode. I’ll do some SO searches and then post a question about the most efficient way to balance security vs speed when running searches. I appreciate your assistance. – Lance Samaria Jul 24 '18 at 17:44