2

So I'm stuck for half a day here, I'm trying to get all the subjects of Arya but I'm having a hard time doing it.

Here's the sample structure in Firebase.

-Subjects
    -math
        id: 1
        name: Math
        -students
            -Arya
                id: 1
                name: Arya
            -JonSnow
                id: 2
                name: JonSnow
            +justsomename
    +science
    +english
    +history
    +computer

Then I found this one Querying in Firebase by child of child.

I tried this

ref.queryOrdered(byChild: "students/name").queryEqual(toValue: "Arya").observeSingleEvent(of: .value, with: { snapshot in

        print(snapshot)
    })

ref == Subjects

but this is the return

Snap (subjects) <null>

Is the query correct and I'm just doing something wrong?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
MaappeaL
  • 514
  • 1
  • 8
  • 16
  • What value are you trying to get? – Tony Merritt Aug 17 '17 at 11:25
  • I'm trying to get all the subjects with a student named Arya. – MaappeaL Aug 17 '17 at 11:29
  • @MaappeaL have you tried to separate `students/name`? I don't know if this will solve it but I would give it a try: `child("students").queryOrdered(byChild: "name").queryEqual(toValue:"Arya)"`. What about `ref`, it is pointing to `Subjects/-math`? – ZassX Aug 17 '17 at 11:42
  • I think it is because you are looking for children of subjects that are equal to students but it can't find a child students because that is another child of a subject such as math. you need to get it to check each subject child i.e. math for the query you have. – Tony Merritt Aug 17 '17 at 11:47
  • try to hard code in the directory to see if its the way you are looking. i.e ref.child("math").queryOrdered(byChild: "students/name").queryEqual(toValue: "Arya").observeSingleEvent(of: .value, with: { snapshot in print(snapshot) }) // if this gives you a print out of math you know you need to get it to search each subject name for your query – Tony Merritt Aug 17 '17 at 11:56
  • @ZassX I'll try it later, ref is pointing to Subjects only – MaappeaL Aug 17 '17 at 11:57
  • i think that is where your issue is because it is looking for students in subjects not subjects/math on so on – Tony Merritt Aug 17 '17 at 11:58
  • @Tony Merritt I alredy tried hardcoding it ang I'm able to get the answer. To be honest, I'm already getting the result that I want by fetching all the subjects and quering from there, like your suggestion on your 2nd comment. But I'm bothered of nestead quering and looking for better solution. – MaappeaL Aug 17 '17 at 12:00
  • 1
    Firebase Database queries can filter by a property at a known path. There is no way to query for properties at a dynamic path as you're trying to do. This means you'll need to modify your data model to allow the query you want, e.g. store a top-level list of "classes per student". Also see https://stackoverflow.com/questions/27207059/firebase-query-double-nested – Frank van Puffelen Aug 17 '17 at 14:42
  • @FrankvanPuffelen I guess I'll have to modify the structure of my data. Thank you for your answer and I'm glad to know that what I want to happen is not possible and not waste time anymore. – MaappeaL Aug 17 '17 at 17:52

1 Answers1

-1

Maybe something like this.... could work...

var subjects = [String]()

    ref.observeSingleEvent(of: .value, with: { snapshot in

        let value = snapshot.value as? NSDictionary
        let postsIds = value?.allKeys as! [String] // this will put all the subjects such as math into an array called postIDs

        for postId in postsIds { //this is going to cycle through the array and check each one for your student
            let refToPost = Database.database().reference(withPath: "Subjects" + postId)
            refToPost.observeSingleEvent(of: .value, with: { snapshot in
                if snapshot.hasChild("Arya") {



                    self.subjects.append(snapshot)
                }
            })
        }
    })
  print("this is the ist of subjects with my student: \(subjects)")
Tony Merritt
  • 1,177
  • 11
  • 35
  • This works, but is not the best practice. Why? Because what you do here is read ALL results from the node and then filter them out on the phone. Keep in mind that since you read all the data there may be few thousand results that you will be reading. What you should do instead is use `queryOrdered` and already filter results when executing query. This way you will get only few results in the response instead of everything inside that node. – ZassX Aug 17 '17 at 12:38
  • what if we change `refToPost.observeSingleEvent(of: .value, with: { snapshot in` to `refToPost.queryOrdered(byChild: "students/name").queryEqual(toValue: "Arya").observeSingleEvent(of: .value, with: { snapshot in` – Tony Merritt Aug 17 '17 at 12:57
  • This is what OP already has. But yes, this is the right way of doing it. – ZassX Aug 17 '17 at 14:13
  • I already did this but I'm bothered of the this solution, so I'm looking for a better way to do it. Thanks anyway. – MaappeaL Aug 17 '17 at 17:53