如何从实时数据库 firebase 读取嵌套数据

How to read nested data from realtime database firebase

我的数据库结构如下:

{
  "username123" : {
    "6642" : {
      "latitude" : 37.861639,
      "longitude" : -4.785556,
      "name" : "CEPSA"
    }
  }
}

这个想法是每个用户都会有一个最喜欢的加油站列表,由他们的 ID 标识(示例中为 6642)。但是,我不知道如何获取数据。有什么帮助吗? 编辑:我试过了,但它显然不起作用,因为我找回了整个东西,我只是不知道如何获取 ID、纬度、经度和名称。

ref.child(user).getData(completion:  { error, snapshot in
        guard error == nil else {
            print(error!.localizedDescription)
            return;
        }
        if let gasStationDict = snapshot.value as? [String:String] {
            guard let id = snapshot.value, let name = gasStationDict["name"], let longitude = gasStationDict["longitude"], let latitude = gasStationDict["latitude"] else { return }
            let gasStation = GasStation(name: name, longitude: longitude, latitude: latitude, favorita: true, id: id)
         }
    });

ref 初始化如下:

var ref: DatabaseReference! = Database.database().reference()

并且用户是:

guard var user = UserDefaults.standard.string(forKey: "User") else { return }

主要问题是问题中出现的 Firebase 结构与代码不匹配:

user_id
   gas_station_id
      name

代码正试图像这样读取它

if let gasStationDict = snapshot.value as? [String:String]

结构更像这样[String: [String: String]]或者可能[String: [String: Int]]

我建议使用 .childSnapshot 获取深层嵌套数据的另一种解决方案。它更容易阅读,也更容易维护

我还建议更改结构。在 NoSQL 数据库中,最好的做法通常是将节点键与它们包含的数据分离。

例如,在您的结构中,6642 是站号。如果将来站点 ID 发生变化怎么办?你实际上必须遍历整个数据库,搜索它,删除那些节点和它们包含的任何内容,然后 re-write 它们。呃!

这是一个更好的结构

{
  "username123" : {
    a_firebase_generated_node_key : { //using .childByAutoId to create
      "latitude" : 37.861639,
      "longitude" : -4.785556,
      "name" : "CEPSA"
      "station_id: "6652"
    }
  }
}

现在您可以更改电台的任何方面,而不必更改对它的任何引用。

然后使用childSnapshot

读取和打印所有站的代码
func printUsersGasStations() {
    let ref = self.ref.child("gas_stations").child("username123")
    ref.getData(completion: { error, snapshot in
        if let err = error {
            print(err.localizedDescription)
            return
        }
        
        //this next line takes all of the stations and creates
        //   an ordered array of them as DataSnapshots
        let allStationsSnap = snapshot.children.allObjects as! [DataSnapshot]

        for stationSnap in allStationsSnap {
            let stationId = stationSnap.childSnapshot(forPath: "station_id").value as? String ?? "No Station ID"
            let lat = stationSnap.childSnapshot(forPath: "lat").value as? Double ?? 0.0
            let lon = stationSnap.childSnapshot(forPath: "lon").value as? Double ?? 0.0
            let name = stationSnap.childSnapshot(forPath: "name").value as? String ?? "No Name"
            print(stationId, lat, lon, name)
        }
    })
}