swift - Firestore 在快照中查询快照?
问题描述
每当有人回复用户评论过的帖子时,我都会尝试收听任何通知。下面是我的数据库结构的外观。
- 帖子:(收藏)
- 帖子 1:(文件)
- 回复:[用户2,用户3]
- 回复:(收藏)
- 回复1:(文件)
- 所有者 ID:[用户 2]
- 回复2:(文件)
- 所有者 ID:[用户 3]
- 回复1:(文件)
- 回复:(收藏)
- 回复:[用户2,用户3]
- 帖子 1:(文件)
目前我的代码有 2 个快照监听器。第一个监听 Posts 集合,其中用户位于“回复”数组中。然后第二个监听 Replies 集合,它返回所有添加了 != 当前用户的文档。当检测到新回复时,它将设置标签栏项目的标记。
这目前有效,但我很好奇是否有更好的方法。
func getNotifications() {
database.collection("Posts")
.whereField("replies", arrayContains: userData["userId"]!)
.order(by: "timestamp", descending: true)
.limit(to: 70)
.addSnapshotListener() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
}
else {
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(err!)")
return
}
snapshot.documentChanges.forEach { documentd in
if (documentd.type == .added) {
let dataTemp = documentd.document.data()
let ifUser = dataTemp["ownerId"] as! String
if(ifUser == self.userData["userId"]!) {
database.collection("Posts")
.document(documentd.document.documentID)
.collection("Replies")
.whereField("timestamp", isGreaterThan: dataTemp["timestamp"] as! Int)
.addSnapshotListener() { (querySnapshot3, err) in
if let err = err {
print("Error getting documents: \(err)")
}
else {
guard let snapshot = querySnapshot3 else {
print("Error fetching snapshots: \(err!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) {
let temp = diff.document.data()
if((temp["ownerId"] as! String) != self.userData["userId"]!) {
print("new reply")
newArr.append(diff.document.data())
let data = diff.document.data()
let firebaseTime = data["timestamp"] as! Int
let date = lround(Date().timeIntervalSince1970)
if(firebaseTime+10 > date) {
self.tabBar.items![2].badgeValue = "●"
self.tabBar.items![2].badgeColor = .clear
self.tabBar.items![2].setBadgeTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for:.normal)
}
}
}
}
}
}
}
else {
database.collection("Posts")
.document(documentd.document.documentID)
.collection("Replies")
.whereField("ownerId", isEqualTo: self.userData["userId"]!)
.order(by: "timestamp", descending: false)
.limit(to: 1)
.getDocuments() { (querySnapshot2, err) in
if let err = err {
print("Error getting documents: \(err)")
}
else {
var timestamp = Int()
for documentde in querySnapshot2!.documents {
let temp = documentde.data()
timestamp = temp["timestamp"] as! Int
database.collection("Posts")
.document(documentd.document.documentID)
.collection("Replies")
.whereField("timestamp", isGreaterThan: timestamp)
.addSnapshotListener() { (querySnapshot3, err) in
if let err = err {
print("Error getting documents: \(err)")
}
else {
guard let snapshot = querySnapshot3 else {
print("Error fetching snapshots: \(err!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) {
let temp = diff.document.data()
if((temp["ownerId"] as! String) != self.userData["userId"]!) {
print("new reply")
newArr.append(diff.document.data())
let data = diff.document.data()
let firebaseTime = data["timestamp"] as! Int
let date = lround(Date().timeIntervalSince1970)
if(firebaseTime+10 > date) {
self.tabBar.items![2].badgeValue = "●"
self.tabBar.items![2].badgeColor = .clear
self.tabBar.items![2].setBadgeTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], for:.normal)
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
解决方案
您的代码不仅有两个侦听器,而且您感兴趣的用户曾经回复过的每个帖子都有一个侦听器。这将很快导致糟糕的性能,并且可能会使您的应用程序崩溃,因为 Firestore 限制每个客户端 100 个侦听器。
我建议重新设计您的数据模型:
- 用户曾经回复过的帖子只有一个听众(您的第一个听众)
- 在每个回复增加一个回复计数器在 post doc 中,这将触发上面的快照。
- 优化 1:在帖子的每个操作上,您可以设置一个字段,该字段仅对回复
lastactiontype
具有特定值。reply
这样,快照仅在回复时触发。 - 优化 2:将
timestamp
每个动作的字段设置为当前时间,并且只拉取快照中的最后 n 个(例如 10 个)帖子,这将限制加载时的读取次数。当您的应用程序离线并重新在线并且快照的所有 n 个帖子都已更改时,您将必须实现一些特殊的逻辑来处理这种情况。如果您的应用程序要扩展,这是必须的(您不想要一个对包含 100k 文档的集合没有限制的快照......)
例子:
firestore.collection("Posts")
.where( "lastaction", "==" , "reply")
.where( "replies", "array-contains", uid)
.orderBy("timestamp", "desc").limit(10)
推荐阅读
- c# - 从 Twitch Clip URL 中提取 ID
- reactjs - React 路由在与 webpack.config.js 一起使用时正常工作,但在从 webpack.config.js 重定向时不工作
- java - 比较两个arrayList得到共同的值,它应该不影响原始值
- codenameone - 当 App 在 CN1 崩溃时会调用 stop() 方法
- angular - 模态无法使用 NgbActiveModal 关闭
- php - Laravel 5.4 中的 Group By 替代方案
- c# - 使用 iText 7 PDF 进行表格拉伸和单元格对齐
- javascript - 为什么增量器打印 3 即使条件检查小于 3?
- python-3.x - 使用命令行参数调用类方法
- python - git-flask-python :删除pycache和flask会话文件夹是否安全