如何通过Firebase查询仅获取指定键CityState的列表?
如何在Firebase Realtime Database中直接获取特定字段的列表(Swift 3.2)
问题描述
我的Firebase数据结构如下:
2014 { 0 { CityState: "New York, NY", PinCode: "12345" }, 1 { CityState: "Los Angeles, CA", PinCode: "67890" } }
我需要获取所有CityState字段的列表,但目前只能先获取全量数据再过滤,代码如下:
ref?.child("2014").observeSingleEvent(of: .value, with: { snapshot in if let item = snapshot.value as? [Dictionary<String, Any>] { for items in item { print(items["CityState"]) } } else { print (snapshot.value) } })
由于数据量庞大,这个操作耗时太长。请问有没有Firebase查询方式可以直接获取CityState键的数值列表?我使用的是Swift 3.2和Xcode 9.2。
解答
很遗憾,Firebase Realtime Database没有直接的查询API可以跨多个节点只提取特定字段——它的读取逻辑是基于节点层级的:要么读取整个节点(就像你现在的做法),要么读取某个指定的子节点,但没办法跳过其他字段只返回CityState。
不过我们有两个优化方向可以解决这个问题:
1. 优化数据结构(推荐方案)
NoSQL数据库的核心设计思路是为查询建模,如果你的业务经常需要单独获取CityState列表,最好在数据库中预存一个专门的节点来存储这些值。比如新增一个2014_CityStates节点:
2014_CityStates { 0: "New York, NY", 1: "Los Angeles, CA" }
这样你只需要直接读取这个节点就能拿到所有CityState的值,完全不需要下载PinCode这类多余数据,性能会提升非常明显。
注意:写入数据时,要同时更新主数据节点和这个
CityStates节点,可以用Firebase的批量更新功能来保证数据一致性:let updates = [ "/2014/0/CityState": "New York, NY", "/2014/0/PinCode": "12345", "/2014_CityStates/0": "New York, NY" ] ref?.updateChildValues(updates)
2. 优化现有读取代码(临时方案)
如果暂时没法修改数据结构,你可以优化现有代码的内存处理逻辑,虽然还是会下载全量数据,但能减少不必要的解析开销:
ref?.child("2014").observeSingleEvent(of: .value, with: { snapshot in // 直接遍历快照的子节点,避免把整个节点转成字典数组 guard let childSnapshots = snapshot.children.allObjects as? [DataSnapshot] else { print("No valid data found") return } for child in childSnapshots { // 直接提取指定路径的子快照值 if let cityState = child.childSnapshot(forPath: "CityState").value as? String { print(cityState) } } })
这种写法不需要将整个节点数据转成字典数组,而是直接操作快照对象,内存占用会更低,解析速度也会快一些。
内容的提问来源于stack exchange,提问作者Rookie
相关产品推荐
相关产品推荐

