swift - Firebase 和 Swift 如何按子值提取特定记录?
问题描述
我正在使用带有 swift 的 Firebase(确切地说是 SwiftUI),并且由于我的数据库包含许多记录(超过 10k 条记录),我试图只从数据库中提取相关数据(否则它每次都会提取所有数据,这将浪费)。
我认为我应该使用 .indexOn 但我真的不知道该怎么做(我对 json 没有太多经验)。
这是我尝试使用的 SWIFT 代码:
ref.child("Items").observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
// Doing stuff here.
}
})
这是我的数据结构:
tbl (the actual table):
items:
____:
serial:
date:
more parameters...:
____:
serial:
date:
等等...
空白点 (___:) 表示由 Firebase 自动生成的名称(只是从 0 到表中记录数量的随机数),我想通过查询提取包含匹配序列的特定记录。
这就是我在 Firebase DB 中的规则的样子:
{
"rules": {
".read": true,
".write": false
}
}
我应该如何在我的 Firebase 规则中使用 .indexOn?或者还有其他选择可以得到我想要的吗?
提前致谢。
更新:
我正在尝试从查询中获取特定记录。根据我上面指定的数据结构,我要获取的是序列号与我将输入到查询中的序列号匹配的孩子的序列号和日期。
假设我想在查询中使用 X8M9320C。我想得到的是序列号(X8M9320C)和表中的日期。
此外,___: 的命名是一个自动生成的数字,当我将 json 文件上传到 Firebase 时会自动初始化。
经过一些调试,我看到运行查询后,我从行中得到 0 个值:
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
完整代码:
let serial = "XCM8320CMW"
let myDataRef = self.ref.child("tbl")
let itemsRef = myDataRef.child("items")
let query = itemsRef.queryOrdered(byChild: "serial").queryEqual(toValue: serial)
query.observeSingleEvent(of: .value, with: { snapshot in
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
guard let firstChild = childSnaps.first else {return}
let date = firstChild.childSnapshot(forPath: "date").value as? String ?? "No Date"
print(date)
})
解决方案
TL;博士
我在下面解决了一个编码问题,OP正在搜索的字符串就是这个
X8M9320C
但是存储在 Firebase 中的是这个
注意存储字符串前后的所有空格(空格键字符)。两者不相等,这就是为什么我下面的查询不起作用的原因。
-- 更长的答案:
澄清一下,Firebase 没有表格;它有键:值对,也称为父节点和子节点,其中父节点是键,子节点是值,也可以是一对键:值。
这听起来像是文档中介绍的基本 Firebase查询。
鉴于您的问题中的结构:
my_data
items
item_0
serial: "OU812"
date: "20200427"
more parameters...:
item_1
serial: "X8M9320C"
date: "20200513"
more parameters...:
这是查询 X8M9320C 的序列并从该节点打印日期的查询。请记住,查询可能会返回多个结果,我们需要遍历所有返回的节点。
func queryForItem() {
let serial = "X8M9320C"
let myDataRef = self.ref.child("my_data")
let itemsRef = myDataRef.child("items")
let query = itemsRef.queryOrdered(byChild: "serial").queryEqual(toValue: serial)
query.observeSingleEvent(of: .value, with: { snapshot in
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
for snap in childSnaps {
let date = snap.childSnapshot(forPath: "date").value as? String ?? "No Date"
print("serial: \(serial) has a date of \(date)")
}
})
}
和输出
serial: X8M9320C has a date of 20200513
如果您知道永远不会返回任何内容或返回一个节点(例如,如果保证序列是唯一的),您可以消除 for 循环并执行此操作
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
guard let firstChild = childSnaps.first else {return}
let date = firstChild.childSnapshot(forPath: "date").value as? String ?? "No Date"
print(date)
推荐阅读
- ios - 在 Swift 中解压缩 Base64 编码的图像字节
- ruby - 将 Ruby 块中的变量分配给更高的范围
- ruby-on-rails - 输入后Rails覆盖数据库中的值
- docker - 在每次部署中,构建一个包含应用程序的新 docker 映像而不只是更新应用程序有什么优势?
- elasticsearch - 具有动态字段的嵌套聚合 - elasticsearch
- mysql - Excel for Mac 2016 中是否有 ADODB.connection ADODB.recordset 的等价物?
- java - 连接两个类
- install4j - 安装 DMG 时如何显示带有更新 7.0.8 的 install4j 图标
- java - Spring批处理:使用名称,Gradle,Mongodb创建bean时出错
- xamarin.forms - Prism DI container from Android background service