【问题标题】:How to write to the last child of a Firebase ref in Swift?如何在 Swift 中写入 Firebase ref 的最后一个孩子?
【发布时间】:2016-12-31 02:47:09
【问题描述】:

我正在努力以所需的方式将数据写入 Firebase。

情况:我想为每个用户存储多个“行程”。每个“行程”都包含带有纬度、经度、高度和时间戳的位置。 在某些条件下,我想在最近的“旅行”中添加一个新位置。

数据结构如下:

- root
-- users
--- userID
---- trips
------ trip1
------- location
------ trip2
------- location

将位置添加到最近一次旅行(在本例中为trip2)的最佳方式是什么?

我曾希望类似的事情是可能的:

func setupFirebase() {
        ref = FIRDatabase.database().reference()
        userRef = ref.child("users")

        userID = FIRAuth.auth()?.currentUser?.uid
        tripsRef = self.userRef.child(userID!).child("trips")
        currentTripRef = tripsRef.queryLimited(toLast: 1)

    }

然后我可以简单地去:

currentTripRef.child(dateString).setValue([
                "timestamp": dateString,
                "lat": lat,
                "lng": lng,
                "alt": alt
                ])

无论我需要在哪里写东西。这显然不是正确的方法,但我似乎无法弄清楚正确的方法是什么。

我想我可以观察我的tripsRef,获取一个键数组,然后在该观察函数内部使用最后一个键写入子参考。但这听起来一点效率都没有。

对此有什么解决办法吗? 提前致谢!

【问题讨论】:

  • 为什么这看起来不正确?
  • 您没有从 .queryLimited(toLast: 1) 获得 Firebase Ref,因为此属性返回的是查询,而不是 ref。
  • 我完全错过了observeEventType 不在那里 :(!你为什么不使用observeEventType 获得 currentTripRef 的值?这会给你最后一个对象,在这种情况下 trip2。而在 snapshot 中,只需通过迭代快照子项(在本例中只有一个对象)并使用 childSnapshot.key 获取密钥来访问值?所以你现在有了trip2 键,您可以只更新该节点的值!
  • 这与我的想法很接近。我将发布一个带有工作解决方案的答案,以讨论优化潜力。你介意看看吗?

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

首先,请记住,将节点名称与数据分离是最佳做法。您可能正在这样做,但想强调这一点。

这是一个处理用户及其旅行的建议结构

root
  users
    uid_0
      name: "Jamie"
    uid_1
      name: "Adam"
  trips
    -Yijaisioaooisd
       user_id: "uid_0"
       trip_number: 1
       trip_name: "France"
       locations
         -Yuijiaissso
            location_name: "Bordeaux"
            stop_number: 1
         -Yijs9ojnas9
            location_name: "Burgundy"
            stop_number: 2
         -Yijispoais
            location_name: "Châteauneuf-du-Pape"
            stop_number: 3

如果您想在 uid_0 的法国之旅中添加另一个站点/位置,参考是

let locationsRef = rootRef.child("trips").child("-Yijaisioaooisd").child("locations")

然后

let anotherLocationRef = locationsRef.childByAutoId()
let stopDict = ["location_name": "Médoc", "stop_number": 4]
locationsRef.setValue(stopDict)

话虽如此,在某些情况下,您可能希望对数据进行非规范化并分解位置(用于查询等)

原来如此

locations
   trip_id: "-Yijaisioaooisd"
   locations:
      -Yuijiaissso
         location_name: "Bordeaux"
         stop_number: 1
      -Yijs9ojnas9
         location_name: "Burgundy"
         stop_number: 2
      -Yijispoais
          location_name: "Châteauneuf-du-Pape"
          stop_number: 3

根据评论,添加一些附加信息:

如果您想在 uid_0 的最新行程中添加另一个站点,有多种选择,实际答案将取决于数据的结构。

使用 queryLimitedToLast,可以查询位置节点中的最后一个停靠点,以获取停靠点编号(上例中的 3)到您可以将其递增的位置,然后写出下一个停靠点。如果您知道父键 -Yijaisioaooisd,这将起作用,因为 ref 将是 -Yijaisioaooisd/locations。

如果您不知道父键,您可以通过在 trips 节点上查询 user_id 等于 uid_0 轻松获得它。这将返回一个快照。然后 snapshot.key 会提供 -Yijaisioaooisd 父键。

【讨论】:

  • 嘿,Jay,感谢您提供这个非常有用的概述。如果我想写信给最近的旅行,我将如何为 uid_0 的法国旅行添加另一个站点/位置?我是否必须使用查询来观察 rootRef 以过滤 uid_0,然后按最高的 trip_number 值排序,只过滤最高的结果?然后获取它的 .ref 属性?据我了解,问题的核心(不知道行程的“-Yijaisioaooisd”UID,应该是最新的)还没有解决。有什么提示吗?谢谢你,先生!
  • @timgilbert7331 我在答案底部添加了其他信息以回答您的后续评论问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 2018-02-12
  • 1970-01-01
相关资源
最近更新 更多