Firebase query using a list of ids (iOS)
Asked Answered
P

2

6

I have an NSArray containing multiple ids. Is there a way in Firebase where I can get all the object with the ids in the array?

I am building a restaurant rating app which uses GeoFire to retrieve nearby restaurants. My problem is that GeoFire only returns a list of ids of restaurant that are nearby. Is there any way i can query for all the object with the ids?

Puryear answered 10/4, 2017 at 12:30 Comment(0)
U
4

No, you can't do a batch query like that in Firebase.

You will need to loop over your restaurant IDs and query each one using observeSingleEvent. For instance:

let restaurantIDs: NSArray = ...
let db = FIRDatabase.database().reference()
for id in restaurantIDs as! [String] {
    db.child("Restaurants").child(id).observeSingleEvent(of: .value) {
        (snapshot) in
        let restaurant = snapshot.value as! [String: Any]
        // Process restaurant...
    }
}

If you are worried about performance, Firebase might be able to group all these observeSingleEvent calls and send them as a batch to the server, which may answer your original question after all ;-)

Unscientific answered 10/4, 2017 at 12:56 Comment(1)
There is no way to combine these calls, not is one needed. See #35932026.Ritchey
P
1

I know that this answer is considered accepted but I have had really good success using promise kit with the method frank posted with his javascript link Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly and just wanted to share the swift version

So I have a list of users ids that are attached to a post like this: also these methods are in my post class where I have access to the post id from firebase

// this gets the list of ids for the users to fetch ["userid1", "userid2"....]



func getParticipantsIds() -> Promise<[String]> {

    return Promise { response in
        let participants = ref?.child(self.key!).child("people")
        participants?.observeSingleEvent(of: .value, with: { (snapshot) in
            guard let snapshotIds = snapshot.value as? [String] else {
                response.reject(FirebaseError.noData)
                return
            }
            response.fulfill(snapshotIds)
        })

    }
}




// this is the individual query to fetch the userid


 private func getUserById(id:String) -> Promise<UserData> {
       return Promise { response in

           let userById = dbRef?.child("users").child(id)
           userById?.observeSingleEvent(of: .value, with: { (snapshot) in
               guard let value = snapshot.value else {
                   response.reject(FirebaseError.noData)
                   return
               }
               do {
                   let userData = try FirebaseDecoder().decode(UserData.self, from: value)
                   response.fulfill(userData)
               } catch let error {
                   response.reject(error)
               }
           })

       }
   }


// this is the where the magic happens


func getPostUsers(compeltion: @escaping (_ users:[UserData], _ error:Error?) -> ()){

    getParticipantsIds().thenMap { (id) in
        return self.getUserById(id: id)
    }.done { (users) in
        compeltion(users, nil)
    }.catch({ error in
        compeltion([], error)
    })

}
Pinnace answered 2/4, 2020 at 20:47 Comment(1)
Have had good success taking this approach with RxSwift using the zip operator. Was then able to denormalize my data as suggested by Firebase in the docs.Antrorse

© 2022 - 2024 — McMap. All rights reserved.