6

Let's say I have a structure like this:

-users
  -user1_uid
    name
    distance
    age

How would I do a query like (Find users with distance <100 and age between 20 and 25)?

I have tried the standard method

        let recentPostsQuery = (ref?.child("users").queryOrderedByChild("age").queryStartingAtValue("20"))!

M problem is, that is does not appear to be possible to query multiple childs (like combining age and distance filtering). Did something change in this regard compared to Firebase a few months ago? Filtering them locally after the first query is not an option, I believe, as there could be potentially thousands of objects.

Nico Reese
  • 261
  • 6
  • 14
  • What have you tried so far? Remember Stack Overflow is here to help you, not to do your work for you. – André Kool May 20 '16 at 11:00
  • Cross post. Try to keep posts in one place to prevent duplication. [Database query/filtering](https://groups.google.com/forum/#!searchin/firebase-talk/queryStartingAtValue$3A/firebase-talk/VUoOBAtzCAo/LoCApvVjFgAJ) – Jay May 20 '16 at 17:52

2 Answers2

8

My first choice would be to query for all the users between 20 and 25 and then filter in code for ones with a distance < 100.

The question states filtering in code is not an option but I wanted to include it for completeness for situations where it was several thousand nodes or less:

    struct User { //starting with a structure to hold user data
        var firebaseKey : String?
        var theAge: Int?
        var theDistance: Int?
    }

    var userArray = [User]() //the array of user structures

    usersRef.queryOrderedByChild("age").queryStartingAtValue(20)
     .queryEndingAtValue(25).observeEventType(.Value, withBlock: { snapshot in

        for child in snapshot.children { //.Value so iterate over nodes

            let age = child.value["age"] as! Int
            let distance = child.value["distance"] as! Int
            let fbKey = child.key!

            let u = User(firebaseKey: fbKey, theAge: age, theDistance: distance)

            userArray.append(u) //add the user struct to the array
        }

        //the array to contain the filtered users
        var filteredArray: [User] = []
        filteredArray = userArray.filter({$0.theDistance < 100}) //Filter it, baby!

        //print out the resulting users as a test.
        for aUser in filteredArray {

            let k = aUser.firebaseKey
            let a = aUser.theAge
            let d = aUser.theDistance

            print("array: \(k!)  \(a!)  \(d!)")

        }

    })
}

Now a potential super simple answer.

    let usersRef = self.myRootRef.childByAppendingPath("users")

    usersRef.queryOrderedByChild("age").queryStartingAtValue(20)
     .queryEndingAtValue(25).observeEventType(.ChildAdded, withBlock: { snapshot in

        let distance = snapshot.value["distance"] as! Int

        if distance < 100 {
            let age = snapshot.value["age"] as! Int
            let fbKey = snapshot.key!

            print("array: \(fbKey)  \(age)  \(distance)")
        }
    })

Notice that we are leveraging .ChildAdded instead of .Value so each node is read in one at a time - if the distance is not what we want, we can ignore it and move on to the next.

Jay
  • 34,438
  • 18
  • 52
  • 81
  • Will the queryStartingValue and queryEndingValue also work with double values or just integers? – Good Game Industries Jul 04 '17 at 02:02
  • 1
    @GoodGameIndustries Firebase knows about NSString, NSNumber, NSDictionary and NSArray (please avoid arrays). See [Read & Write Data](https://firebase.google.com/docs/database/ios/read-and-write). So it will work with anything you can put into those data types, as long as whatever it is, is one of those types. That being said, the answer is yes, you can use .startingAt and .endingAt with doubles, ints, strings. – Jay Jul 04 '17 at 12:37
  • did u get its answer I have the same issue like u? – jagdeep singh Jul 29 '18 at 00:27
  • @jagdeepsingh This question is from 2016, two years ago. What issue are you having? Is it something you can ask in a question that isn't a duplicate? If so, post your question and we'll take a look - remember to include code and your Firebase structure (as text please, no images) – Jay Jul 29 '18 at 12:12
  • @Jay https://stackoverflow.com/questions/51576643/how-can-i-get-user-nearby-my-location-in-geofire-firebase can u please look at it – jagdeep singh Jul 29 '18 at 14:48
1

Firebase can't combine always the conditions. How to query based on multiple conditions in Firebase?

But, using the new firebase API, this post can give some hints: Query based on multiple where clauses in firebase

Community
  • 1
  • 1
Alexis Clarembeau
  • 2,776
  • 14
  • 27