5

I'm quite new to Firebase and Swift and I'm having some trouble when it comes to querying. So there are basically two things I'd like to do:

  1. Query my users and find only those that contain a certain String in their name (or email address) and add them to an array.
  2. Get all of my users and add them to an array.

The relevant part of my data for this question looks like this: enter image description here

As you can see, I'm using the simplelogin of Firebase (later I'd like too add Facebook login) and I'm storing my users by their uid.

A part of my rules file looks like this:

"registered_users": {
    ".read": true,
    ".write": true,
    ".indexOn": ["name"]
 }

So everybody should have read and write access to this part of my data.

I also read the "Retrieving Data" part of the Firebase iOS Guide on their website and according to that guide, my code on getting all the users names and email addresses should work, at least I think so. But it doesn't. Here is my code:

func getUsersFromFirebase() {
        let registeredUserRef = firebaseRef.childByAppendingPath("registered_users")
        registeredUserRef.queryOrderedByChild("name").observeSingleEventOfType(.Value, withBlock: { snapshot in
            if let email = snapshot.value["email"] as? String {
                println("\(snapshot.key) has Email: \(email)")
            }
            if let name = snapshot.value["name"] as? String {
                println("\(snapshot.key) has Name: \(name)")
            }
        })
    }

I noticed, that in the firebase guide, they always used the type ChildAdded and not Value, but for me Value makes more sense. The output with Value is nothing and the output with ChildAdded is only one user, namely the one that is logged in right now.

So my questions are:

  1. Can I do this query with my current data structure or do I have to get rid of storying the users by their uid?
  2. If yes, how would I have to change my code, to make it work?
  3. If no, what would be the best way to store my users and make querying them by name possible?
  4. How can I query for e.g. "muster" and get only the user simplelogin:1 (Max Mustermann)?

I hope my description is detailed enough. Thx in advance for your help.

Supplement:

The weird thing is, that the "Retrieving Data" guide says, that querying and sorting the following data by height is possible.

Data:

enter image description here

Querying code: enter image description here

And isn't that exactly the same that I intent to do?

X.X_Mass_Developer
  • 717
  • 1
  • 8
  • 23

2 Answers2

2

I have run into similar situations where I wanted to pull out data from child nodes.

https://groups.google.com/d/msg/firebase-talk/Wgaf-OIc79o/avhmN97UgP4J

The first thing I can recommend is to not think of Firebase query's as SQL queries as they are not. They are like a light duty query.

Secondly, you need to flatten your data if you want to query, as a query only goes one level deep (can't really query data in child notes)

Lastly - if you don't want to flatten your data, one conceptual option to answer your question;

  1. If possible, ObserveSingleEventOfType:FEventTypeValue on the registered users node. This will read all of the registered users into a snapshot.
  2. Iterate over the snapshot and read each user into an array (as dictionary objects)
  3. Then use NSPredicate to extract an array of users that you want.

I've run numerous tests and performance wise, it's negligible unless you have thousands of users.

Hope that helps!

Jay
  • 34,438
  • 18
  • 52
  • 81
  • Thank you for your answer. But could you pls have another look at my question, because I added something at the end. – X.X_Mass_Developer Mar 25 '15 at 15:15
  • And one more thing, would it be a good idea, to add another entry to my database, that stores the names of all users in the first level (to be able to query it) and the ID in the second level. This way i could look for Max Mustermann in the name-db, get his ID from there and get the rest of his data in the registered_users-db by querying for his ID. Or would that be too much overhead? The problem there is of course, that I wouldn't be able to also look for email addresses unless I create another db entry with email addresses. And that can't be good, right? – X.X_Mass_Developer Mar 25 '15 at 15:23
  • In your getUsersFromFirebase code snippit: The FEEventTypeValue reads in an entire node of data at one time into a single snapshot. You are then responsible for iterating over that snapshot and pulling out the data you want. So inside the block, you would want to leverage the built in functionality ( FDataSnapshot *child in snapshot.children ) {} to get each child. – Jay Mar 26 '15 at 18:32
  • Value Event & Child Added do two different things. The value event is described in the above comment. The Child added event does two things: 1) It reads in each child in a node, one at a time, executing the code in the block once for each child - this gives you the opportunity to say... read in the initial data for a NSTableView. 2) It then waits for a child to be added, and when it does, the block is executed. – Jay Mar 26 '15 at 18:35
-1

To answer your questions

1) Yes, you can query with your current structure. A query can go 1 child deep, but not within a child's children.

2) If yes, how would I have to change my code, to make it work?

Here's a quickie that queries by a users last name:

Firebase *usersNodeRef = your users node 'registered_users'
FQuery *allUsersRef = [usersNodeRef queryOrderedByChild:@"lastName"];
FQuery *specificUserRef = [allUsers queryEqualToValue:@"aLastName"];

[specificUser observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {

  NSDictionary *dict = snapshot.value;
  NSString *key = snapshot.key;

  NSLog(@"key = %@ for child %@", key, dict);

}];

How can I query for e.g. "muster" and get only the user simplelogin:1 (Max Mustermann)?

In your uses node structure, the users are store in nodes with a key.. the key is the simplelogin:1 etc. snapshot.key will reveal that. So it's key/value pair deal...

value = snapshot.value key = snapshot.key

Jay
  • 34,438
  • 18
  • 52
  • 81