如何在Swift中的Firebase查询中应用多个filter?

我正在尝试开发一个应用程序,如出租车预订和在Firebase上存储数据。

但是,从Firebase查询RideDetail(History)的数据时,我遇到了问题。

我想以分页forms获取特定“customer_id”的ride_detail。

我的Firebase数据结构:

{ "ride_details": { "NuEoP2WNPwigsbY1FQy9M150131918189233": { "customer_id": "tstebwLlf4OCRdWhNKO9XCO08xY2", "destination_address": "New Ranip\nNew Ranip\nAhmedabad\nGujarat 380081\nIndia", "destination_lang": 72.55924470000001, "destination_latg": 23.0930152, "discount": "10%", "driver_id": "cIyZQIJ7tsdvF1a9KpRrKucF2o62", "drop_time": "2017-07-29 09:12:21 +0000", "fare": "13.16 Rs.", "payment_time": 150149034812771, "pickup_time": "2017-07-29 09:10:38 +0000", "priceperkm": "10.00 Rs.", "ride_confirm_time": "2017-07-29 09:06:21 +0000", "source_address": "Vastrapur\nVastrapur\nAhmedabad\nGujarat\nIndia", "source_lang": 72.5293244, "source_latg": 23.0350073, "tax": "10%" }, "RH0oZ0Ypbkur3wJM3HMvM150147833457957": { "customer_id": "aYQFbwLlf4OCRdWhNKO9XCO08xY2", "destination_address": "Sarovar Park Plaza Hotels and Resorts Private Limted\nNo 1\nSector 10\nCBD Belapur\nWadala West\nWadala\nMumbai\nMaharashtra 400614\nIndia", "destination_lang": 72.8561644, "destination_latg": 19.0176147, "discount": 0, "driver_id": "cIyZQIJ7tsdvF1a9KpRrKucF2o62", "drop_time": "", "fare": 0, "payment_time": 150149034812772, "pickup_time": "", "priceperkm": 0, "ride_confirm_time": "2017-07-31 05:18:54 +0000", "source_address": "Smokin Joe's Fresh Pizza\nShop No. 2\n3\nGround Floor\nAbhiman II\nWadala West\nThane West\nMumbai\nMaharashtra 400602\nIndia", "source_lang": 72.8561644, "source_latg": 19.0176147, "tax": 0 } } } 

这里“payment_time”是付款完成时的时间戳。

而我想要的回应是这样的:

 { "RH0oZ0Ypbkur3wJM3HMvM150147833457957": { "customer_id": "aYQFbwLlf4OCRdWhNKO9XCO08xY2", "destination_address": "Sarovar Park Plaza Hotels and Resorts Private Limted\nNo 1\nSector 10\nCBD Belapur\nWadala West\nWadala\nMumbai\nMaharashtra 400614\nIndia", "destination_lang": 72.8561644, "destination_latg": 19.0176147, "discount": 0, "driver_id": "cIyZQIJ7tsdvF1a9KpRrKucF2o62", "drop_time": "", "fare": 0, "payment_type": 150149034812772, "pickup_time": "", "priceperkm": 0, "ride_confirm_time": "2017-07-31 05:18:54 +0000", "source_address": "Smokin Joe's Fresh Pizza\nShop No. 2\n3\nGround Floor\nAbhiman II\nWadala West\nThane West\nMumbai\nMaharashtra 400602\nIndia", "source_lang": 72.8561644, "source_latg": 19.0176147, "tax": 0 }, "1trcf0Ypbkur3wJM3HMvM150147833457957": { "customer_id": "aYQFbwLlf4OCRdWhNKO9XCO08xY2", "destination_address": "Sarovar Park Plaza Hotels and Resorts Private Limted\nNo 1\nSector 10\nCBD Belapur\nWadala West\nWadala\nMumbai\nMaharashtra 400614\nIndia", "destination_lang": 72.8561644, "destination_latg": 19.0176147, "discount": 0, "driver_id": "cIyZQIJ7tsdvF1a9KpRrKucF2o62", "drop_time": "", "fare": 0, "payment_type": 150149034812778, "pickup_time": "", "priceperkm": 0, "ride_confirm_time": "2017-07-31 05:18:54 +0000", "source_address": "Smokin Joe's Fresh Pizza\nShop No. 2\n3\nGround Floor\nAbhiman II\nWadala West\nThane West\nMumbai\nMaharashtra 400602\nIndia", "source_lang": 72.8561644, "source_latg": 19.0176147, "tax": 0 } } 

我想要在查询orderedBy“payment_time”中传递的特定“customer_id”的前10条logging。 我也想做同样的分页。 即在第二次查询调用中,必须返回11-20条logging等等。

这个问题和意见有一些不同的标准,但让我在高层次解决;

第一个答案是:Firebase不能被查询一个孩子的价值,然后另一个订购。

简单的查询函数表示:

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

为了完成这个任务,查询你想要的子数据,在这种情况下,所有的客户id为4个节点,然后在代码中进行sorting。 这是一个例子

 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) } }) } 

在这个例子中,我们创build了一个RideClass,其中存储了一些关于骑行的信息,然后创build了一个可以用作tableView数据源的骑乘数组。

然后查询所有用于cust 4的游乐设施。我们有一个循环来显示什么是retreived未分类,然后这个小gem

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

通过pay_time来sorting乘数arrays,这就回答了问题。

假设有十万个乘坐子节点。 加载所有这些数据并在代码中进行sorting可能会使记忆更具挑战性。 你是做什么?

我们利用复合价值; 以及cust_id和pay_time的子节点,我们还包括id_time。 这是一个可能的结构:

  "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" } }, 

然后按照正确的顺序在cust_id4节点中读取一些代码

  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) } }) 

有两件事要注意:

必须迭代快照以维护子序列

“\ uf8ff”是一个Unicode代码级别非常高的字符 – 因为它包含了所有前面的字符。

有两种基本方法可以满足您的要求:

  1. 构造一个按payment_time的查询,限制只包含前10条logging,然后保存对第10条logging的引用,以便可以使用queryStartingAtValuefilter进行后续分页调用。

  2. 使用数据库触发器监听payment_time节点,设置一个firebase云端函数,这样每当用数据库中的值更新空的sting数据时,就会转换数据,从而使数据的组织方式变得微不足道需要在这里。 例如,我将在一个如下所示的path中组织新数据: customer_ride_details/{{customer_id}}/{{ride_id}} 。 而且,当您使用时间戳replacepayment_time空string时,您正在触发该函数。 钥匙应该已经订购了,以供您消费。 您仍然需要像处理选项1一样pipe理分页。