【问题标题】:How to query nested data in Firebase Database?如何查询 Firebase 数据库中的嵌套数据?
【发布时间】:2018-08-23 11:30:44
【问题描述】:

如何进行查询以获取时间戳在 1519912278 ...1520689878 范围内的所有用户的所有预订?在 Firebase 文档中,它声明我可以查询深度嵌套的子级。

根据这个答案,它应该可以工作 https://stackoverflow.com/a/47805607 ,但它返回 null。

我的用户应用程序的流程是什么? :
1. 用户注册
2. 预订时保存在/Users/UID/stripe_customer_created_with_card/bookingNumber{booking object}

为什么我需要位于 /Users 下的所有预订?:
还有一个专为 Workers 设计的应用程序,它可以观察 /Users 节点,每个工人应该能够根据时间戳从 /Users 获取预订。例如,worker1382 可以读取 /Users 在 2018 年 3 月 16 日至 2018 年 3 月 24 日期间进行的预订。

dbRef = FIRDatabase.database().reference().child("Users")
dbRef.queryOrdered(byChild: "TimeStampDateAndTime")
     .queryStarting(atValue: "1519912278")
     .queryEnding(atValue: "1520689878")
     .observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in         
        print(snapshot.value) //returns null
     }

 Users
   UID
    cus_CRC50bSq7rXuHv         //stripe customer id for the user
       617643762                //booking number
         TimeStampDateAndTime: "1521309610"
         Postcode: "E14 9DS"
         BookingNumber:"617643762"

另一个问题:预订对象的父键等于BookingNumber。如果我将父键 617643762 替换为 TimeStampDateAndTime 值 1521309610,我是否能够按时间戳订购预订并最终仅获得在特定范围 1519912278 ...1520689878 内的预订?所以,路径看起来像Users/UID/cus/1521309610: {object goes here}

来自 Firebase 文档

查询也可以由深层嵌套的子级排序,而不是仅向下一层的子级排序。如果您有这样的深层嵌套数据,这将非常有用:

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
       "weight": 5000
     }
   },
}

现在要查询高度,我们使用对象的完整路径而不是单个键。 现在,我的问题是,如果我不知道完整路径,我不能做什么?

 let ref = Firebase(url:"https://dinosaur-facts.firebaseio.com/dinosaurs")
 ref.queryOrderedByChild("dimensions/height").observeEventType(.ChildAdded, withBlock: { snapshot in
 if let height = snapshot.value["height"] as? Double {
     println("\(snapshot.key) was \(height) meters tall")
   }
})

编辑 2

初始结构如下所示:

 {
 "Users" : {
    "I50dHN7wPqPJClPfYDG76gXizdD2" : { //-> user?.uid of a logged in user 
       "cus_CRC50bSq7rXuHv" : {
         "617643762" : {
             "TimeStampDateAndTime" : "1521309610"
          }
        }
     }
   }
 }

修改结构:

{
 "Users" : {
   "I50dHN7wPqPJClPfYDG76gXizdD2" : {
       "1521309610" : { // -> store timeStamp as the immediate child key of UID rather than the booking number
         "TimeStampDateAndTime" : "1521309610",
          "BookingNumber": "617643762"
      }
    }
  }
}


 {
   "UsersProfile":{
     "I50dHN7wPqPJClPfYDG76gXizdD2":{
        "StripeCustomer":"cus_CRC50bSq7rXuHv", // -> store StripeCustomer on the UsersProfile
        "Name": "John Doe"
      }
   }
}

【问题讨论】:

  • 好吧,您正在定义 ref,然后观察 finalRef。此外,您的数据结构对于此查询来说太深了一级 - 如果 TimeStampDateAndTime 是 bookings 节点的子节点,它将起作用。
  • 虽然 ref 和 finalRef 问题已得到纠正,但问题仍然存在,因为您的 firebase 结构对于该查询来说太深了。您将需要创建一个不同的节点来使用该查询,或者重新构建您当前的结构以支持该查询。 Firebase 支持深度查询,但必须正确构建数据库才能使其正常工作。有关示例结构和支持它的查询,请参阅 this question
  • Users 键是什么?我的意思是 firebase 查询适用于自动生成的密钥。
  • 哦,请参阅Deep Query 以获取另一个应该有帮助的问题和答案。在那一个上,查看@frankvanpuffelen 的答案,然后在我的后续答案中查看结构和查询。它是 ObjC,但结构采用适用于深度查询的格式。
  • @TheTiger UID == FIRUser?.uid

标签: swift firebase firebase-realtime-database


【解决方案1】:

您可以查询每个子节点下已知路径的属性。所以你可以在恐龙样本中查询dimensions/weight,也可以从你的数据中查询617643762/TimeStampDateAndTime

但您不能查询*/TimeStampDateAndTime,因为那不是已知路径。

如果您需要获取某个日期范围内所有用户的预订列表,则需要修改数据结构以允许该查询。例如,通过添加顶级预订列表:

"Bookings": {
    "book_617643762"
        Customer: "cus_CRC50bSq7rXuHv"
        TimeStampDateAndTime: "1521309610"
        Postcode: "E14 9DS"
}

有了这个额外的结构,你就可以查询了:

dbRef = FIRDatabase.database().reference().child("Bookings")
dbRef.queryOrdered(byChild: "TimeStampDateAndTime")
     .queryStarting(atValue: "1519912278")
     .queryEnding(atValue: "1520689878")
     .observeSingleEvent(of: .value, with: { (snapshot: FIRDataSnapshot) in         
        print(snapshot.value) //returns null
     }

【讨论】:

  • 如果我有像/Users/UID/timeStamp:{booking Object} 这样的结构,我是否能够获得在时间戳范围内具有子节点 timeStamp 的预订?我在原始问题的最后评论中写了一个更详细的解释。谢谢。
  • 这取决于{booking Object} 的样子。规则很简单:您要排序/过滤的属性必须位于每个子项下的固定路径。如果是,您可以对其进行排序/过滤。如果它不在固定路径上,则无法对其进行排序/过滤。
  • bookingObject 看起来像/Users/UID/timeStamp: {Customer: "cus_CRC50bSq7rXuHv", TimeStampDateAndTime: "1521309610", Postcode: "E14 9DS"}
  • 看起来FIRDatabase.database().reference("Users").queryOrdered(byChild: "timeStamp/TimeStampDateAndTime").queryStarting(atValue: "1519912278").queryEnding(atValue: "1520689878") 应该在那里工作。如果没有,请编辑您的问题以包含确切的 JSON(您可以从数据库控制台导出为文本)和您使用的代码,我们可以看看。
  • 请参阅我原始问题中的编辑 2。在这条路径FIRDatabase.database().reference("Users").queryOrdered(byChild: "timeStamp/TimeStampDateAndTime")中,timeStamp不是孩子的名字,而是Int类型的可变时间戳,比如1521309610
猜你喜欢
  • 2019-03-23
  • 2017-10-11
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多