5
Results
- auto generated ID
  - auto generated ID
       value1: abc
       value2: def

I want to be able to query where "value2" is equal to some specific value. I start with a reference:

let ref = FIRDatabase.database().reference().child("Results")

Since I don't know the auto generated ID's in order to supply a path do I need to get them first in order to get down to value where I can use .queryEqualToValue? If so am I not just grabbing every record to look for a value versus using some kind of index to grab only those where value2 is equal to a value?

In the end I would like a query that returns all "records" where value2 is equal to a certain value. It feels like I need to iterate through every record to do that. I feel like I am missing something here.

Update:

I've tried:

self.ref.queryOrderedByKey().queryEqual(toValue: "def", childKey: "value2").observeSingleEvent(of: .value, with: {(snapshot) in
            print(snapshot) })

This crashes with an error I give in comments below.

I've tried:

self.ref.queryOrdered(byChild: "value2").queryEqual(toValue: "def").observeSingleEvent(of: .childAdded, with: {(snapshot) in

This never executes the closure. If I change the observer to ".value"it returns null.

If I do this:

self.ref.queryOrdered(byChild: "value2").observeSingleEvent(of: .childAdded, with: {(snapshot) in

It will actually sort the data properly. It won't sort properly with ".value" Regardless, adding queryEqual then doesn't work as described above.

C6Silver
  • 3,127
  • 2
  • 21
  • 49
  • Think you might find [this](http://stackoverflow.com/a/14965065/4962554) rather useful for your scenario – eshirima Nov 21 '16 at 05:22
  • I think what I am getting from that is that you cannot do it without iterating through the items. – C6Silver Nov 21 '16 at 06:50
  • @C6Silver I'm currently in the same exact situation as your question. How did you get around it? – Lance Samaria Aug 01 '18 at 23:17
  • @LanceSamaria - Please see the accepted answer and my follow-up comments. The data needs to be restructured. – C6Silver Aug 02 '18 at 18:47
  • @C6Silver hey thanks for the response. I couldn’t figure out how to combine both auto ids. I found it was easier to just duplicate that data at a different node with 1 level then use a combination of auto ids. – Lance Samaria Aug 02 '18 at 18:49

1 Answers1

4

Firebase Database queries properties one level deeper than the location where you run them. They cannot contain a dynamic path under that.

Since you're querying from /Results, you can order by/filter on properties under /Results/$id/PropertyName.

To allow ordering/filtering of all items on properties under /Results/$id1/$id2/PropertyName you will need to change/augment your data structure. For example:

ResultValues
   -auto_generated_ID1_auto_generated_ID2_value1
       value: abc
       path: "auto generated ID/auto generated ID"
   -auto_generated_ID1_auto_generated_ID2_value2
       value: def
       path: "auto generated ID/auto generated ID"

Now you can query with:

ref.child("ResultValues")
   .queryOrderedByChild("value")
   .queryEqual(toValue: "def")
   .observeSingleEvent(of: .value, with: {(snapshot) in
            print(snapshot) })
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Extremely helpful, thank you! At least this saves me time in trying to make this work. The issue with the above approach though is that you cannot easily pull just those items belonging to the first auto generated ID since it is now a combo key. I guess the point then would be to create a separate structure with some duplicated data in order to handle times when you just want all data associated with the first key. – C6Silver Nov 21 '16 at 18:30
  • 1
    Yup. The data duplication part is key here. What precise data you duplicate is up to you. In the example above I just concatenated keys and then added a property for the path to the item under `/Results` – Frank van Puffelen Nov 21 '16 at 19:19