How to apply multiple filter in Firebase query in Swift?

前端 未结 2 1269
余生分开走
余生分开走 2020-12-17 07:37

I am trying developing an application like Taxi booking and storing data on Firebase.

But, I am facing problem while querying data for RideDetail(History) from Fireb

相关标签:
2条回答
  • 2020-12-17 08:05

    The question and comments have some different criteria but let me address it at a high level;

    The first answer is: Firebase cannot be queried for the value of one child and then ordered by another.

    The simple query function expresses that:

    let query = ridesRef.queryOrdered(byChild: "cust_id").queryEqual(toValue: "cust id 4")
    

    To accomplish that task, query for the child data you want, in this case all customer id 4 nodes, and then order in code. Here's an example

    class RideClass {
        var key = ""
        var cust_id = ""
        var pay_time = ""
    
        init(key: String, cust_id: String, pay_time: String) {
            self.key = key
            self.cust_id = cust_id
            self.pay_time = pay_time
        }
    }
    
    var rideArray = [RideClass]()
    
    func populateRideArray() {
        let usersRef = self.ref.child("ride_details")
        let query = usersRef.queryOrdered(byChild: "cust_id").queryEqual(toValue: "cust id 4") 
        query.observeSingleEvent(of: .value, with: { snapshot in 
            for child in snapshot.children {
                let snap = child as! DataSnapshot
                let dict = snap.value as! [String: Any]
                let key = snap.key
                let custId = dict["cust_id"] as! String
                let payTime = dict["pay_time"] as! String
                let ride = RideClass(key: key, cust_id: custId, pay_time: payTime)
                self.rideArray.append(ride)
            }
    
            for ride in self.rideArray {  //unsorted example
                print(ride.pay_time)
            }
    
            self.rideArray.sort { $0.pay_time < $1.pay_time } //sort
    
            for ride in self.rideArray {  //sorted example
                print(ride.pay_time)
            }
        })
    }
    

    In this example, we create a RideClass which stores some info about the ride, and then an array of rides which could be used as a tableView dataSource.

    Then query for all rides that are for cust id 4. We have a loop to show what was retreived unsorted and then this little gem

    self.rideArray.sort { $0.pay_time < $1.pay_time }
    

    which sorts the ride array in place by pay_time, which answers the question.

    Suppose though, there are 100,000 ride child nodes. Loading in all of that data and sorting in code could be challenging memory wise. What do you do?

    We leverage a compound value; along with the child nodes of cust_id and pay_time, we also include id_time. Here's a possible structure:

      "ride_details" : {
        "ride_0" : {
          "cust_id" : "cust id 4",
          "id_time" : "cust id 4_172200",
          "pay_time" : "172200"
        },
        "ride_1" : {
          "cust_id" : "cust id 2",
          "id_time" : "cust id 2_165500",
          "pay_time" : "165500"
        },
        "ride_2" : {
          "cust_id" : "cust id 1",
          "id_time" : "cust id 1_182300",
          "pay_time" : "182300"
        },
        "ride_3" : {
          "cust_id" : "cust id 3",
          "id_time" : "cust id 3_131800",
          "pay_time" : "131800"
        },
        "ride_4" : {
          "cust_id" : "cust id 4",
          "id_time" : "cust id 4_132200",
          "pay_time" : "132200"
        }
      },
    

    and then some code to read in the cust id 4 nodes in the correct order

        let ridesRef = self.ref.child("ride_details")
        let query = ridesRef.queryOrdered(byChild: "id_time")
                            .queryStarting(atValue: "cust id 4_")
                            .queryEnding(atValue: "cust id 4_\\uf8ff")
        query.observeSingleEvent(of: .value, with: { snapshot in
            for child in snapshot.children {
                let snap = child as! DataSnapshot
                let dict = snap.value as! [String: Any]
                let key = snap.key
                let custId = dict["cust_id"] as! String
                let payTime = dict["pay_time"] as! String
                let ride = RideClass(key: key, cust_id: custId, pay_time: payTime)
                self.rideArray.append(ride)
            }
    
            for ride in self.rideArray {  //unsorted example
                print(ride.pay_time)
            }
        })
    

    Two things to note:

    The snapshot must be iterated over to maintain the child sequence

    "\uf8ff" is a character at a very high code level in Unicode - because of that it encompasses all of the preceeding characters.

    0 讨论(0)
  • 2020-12-17 08:09

    There are two basic approaches that may work for your requirements:

    1. construct a query that orders by payment_time, limits to include only the first 10 records, then holds a reference to the 10th record so that you can make subsequent pagination calls with the queryStartingAtValue filter.

    2. Setup a firebase cloud function with a database trigger listening to the payment_time node, such that every time your empty sting is updated with a value in the database you transform the data so that it's organized in such a way that makes it trivial to consume for your needs here. For example - I would organize the new data at a path that looks like this: customer_ride_details/{{customer_id}}/{{ride_id}}. And since you are triggering the function when you replace the payment_time empty string with a timestamp. The keys should be ordered already for you to consume. You will still need to manage your pagination like we did with option 1.

    0 讨论(0)
提交回复
热议问题