Query users by name or email address using Firebas

2019-02-09 23:32发布

问题:

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:

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:

Querying code:

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

回答1:

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!



回答2:

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