Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Swift: queryEqualToValue by childKey is not working

Has anyone have any luck using the function:

.queryEqualToValue(value: AnyObject?, childKey: String?)

Two things:

1) The childKey does not seem to allow deep paths, just direct children

2) I can't get it to work at all! Given my structure:

"post": {
  "groupName": "hello world"
}

If I do a simple:

postRef.queryEqualToValue("hello world", childKey: "groupName").observeSingleEvent( ... )

It does not return any posts at all. Instead I have to do the roundabout way of:

postRef.queryOrderedByChild("groupName").queryEqualToValue("hello world").observeSingleEvent( ... )

to get it to work!

Am I using the above function incorrectly?

like image 777
leonardloo Avatar asked Jun 01 '16 19:06

leonardloo


2 Answers

Xcode 7.2.1
Swift 2.1.1
iOS 9.2
OSX 10.10.5

2) I can't get it to work at all! Given my structure:

"post": {
  "groupName": "hello world"
}

If I do a simple:

postRef.queryEqualToValue("hello world", childKey: "groupName")
postRef.queryEqualToValue("hello world", childKey: "groupName").observeSingleEvent( ... )

I can successfully get the query with the following code:

import UIKit
import Firebase

class ViewController: UIViewController {

    var dbRef: FIRDatabaseReference!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        dbRef = FIRDatabase.database().reference()
        dbRef.child("post").child("groupName").setValue("hello world")

        let postRef = dbRef.child("post")
        print(postRef)

        let query = postRef.queryEqualToValue("hello world", childKey: "groupName")
        print(query)


    --output:--
    (/post {
        en = groupName;
        ep = "hello world";
        sn = groupName;
        sp = "hello world";
    })

1) The childKey does not seem to allow deep paths, just direct children

I'm not seeing that. If I change my code to:

import UIKit
import Firebase

class ViewController: UIViewController {

    var dbRef: FIRDatabaseReference!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        dbRef = FIRDatabase.database().reference()
        dbRef.child("post").child("groupName").child("userId").setValue("hello world")

        let postRef = dbRef.child("post")
        print(postRef)

        let query = postRef.queryEqualToValue("hello world", childKey: "userId")
        print(query)

I get the following output:

(/post {
    en = userId;
    ep = "hello world";
    sn = userId;
    sp = "hello world";
})

However, I cannot get the observers to work--they certainly don't work like the docs say they do.

I delete all my data on Firebase before I run the app.

Edit: Okay, I think I know what's going on with my observers. According to the Retrieve Data section:

Firebase data is retrieved by attaching an asynchronous listener to a FIRDatabase reference FIRDatabaseReference. The listener is triggered once for the initial state of the data and again anytime the data changes.

When I try observing a query, the snapshot in the callback doesn't have any data in it. On the other hand, when I observe a FirDatabaseReference the observer works (somewhat) like I expect.

For example, if I observe a FIRDatabaseReference like this:

import UIKit
import Firebase

class ViewController: UIViewController {

    var dbRef: FIRDatabaseReference!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        dbRef = FIRDatabase.database().reference()
        dbRef.child("post").child("groupName").child("userId").setValue("hello world")

        let postRef = dbRef.child("post")
        postRef.observeEventType(.Value, withBlock: { (snapshot) -> Void in
            print(snapshot)
        })

        sleep(1) //Allow the observer (in another thread) to execute before the following line:
        dbRef.child("post").child("groupName").child("userId").setValue("goodbye Mars")


    }

then the snapshot in the callback has data in it, and I get this output:

Snap (post) {
    groupName =     {
        userId = "hello world";
    };
}
Snap (post) {
    groupName =     {
        userId = "goodbye Mars";
    };
}

But if I observe a FIRDatabaseQuery:

let postRef = dbRef.child("post")
let query = postRef.queryEqualToValue("hello world", childKey: "userID")

query.observeEventType(.Value, withBlock: { (snapshot) -> Void in
    print(snapshot)
})

then the output is:

Snap (post) <null>
like image 104
7stud Avatar answered Oct 27 '22 00:10

7stud


The following is written in the Firebase documentation:

queryEqualToValue Return items equal to the specified key, value, or priority, depending on the order-by method chosen.

Retrieve Data on iOS

The important part is: "depending on the order-by method chosen."

So make sure, you combine the queryEqualToValue-Method with a orderBy-Method.

For example:

    let groupState = "open"

    ref.child("groups").queryOrdered(byChild:"state").queryEqual(toValue:groupState).observe(enventType: .value, with: { snapshot in
        // Returns all groups with state "open"
        for group in snapshot.children {
            print(group)
        }
    })

PS: The variant with childKey is not mentioned in the new Firebase iOS-Guides.

like image 37
Blank Avatar answered Oct 27 '22 00:10

Blank