获取多个 ids 文档 firestore
Get several ids documents firestore
如何从 firestore 获取 ids 文档?
现在我从 backend 得到几个 ids 文档 我需要在 tableview[=80] 中显示收到的 ids 文档=].
在 firestore 我有这个 ids:
xNlguCptKllobZ9XD5m1
uKDbeWxn9llz52WbWj37
82s6W3so0RAKPZFzGyl6
EF6jhVgDr52MhOILAAwf
FXtsMKOTvlVhJjVCBFj8
JtThFuT4qoK4TWJGtr3n
TL1fOBgIlX5C7qcSShGu
UkZq3Uul5etclKepRjJF
aGzLEsEGjNA9nwc4VudD
dZp0qITGVlYUCFw0dS8C
n0zizZzw7WTLpXxcZNC6
例如我的 backend 只找到这个 ids:
JtThFuT4qoK4TWJGtr3n
TL1fOBgIlX5C7qcSShGu
UkZq3Uul5etclKepRjJF
或
aGzLEsEGjNA9nwc4VudD
dZp0qITGVlYUCFw0dS8C
n0zizZzw7WTLpXxcZNC6
我只需要在tableview中显示这三个id。 (但实际上后端 return 我有 100 多个 ID,下面你可以看到疯狂排序这些 ID)
后端 将此 id 添加到临时数组中 var tempIds: [String] = []
那么我如何才能从 firestore 获取那些 ID 并在 tableview 中显示它们?
我使用这个代码:
fileprivate func query(ids: String) {
Firestore.firestore().collection(...).document(ids).getDocument{ (document, error) in
if let doc = document, doc.exists {
if let newModel = Halls(dictionary: doc.data()!, id: doc.documentID) {
self.halls.append(newModel)
self.halls.shuffle()
self.halls.sort(by: { [=10=].priority > .priority })
self.tableView.reloadData()
} else {
fatalError("Fatal error")
}
} else {
return
}
}
}
我需要在后台处理来自 backend 的 ID,处理后需要在 tableview 中显示处理后的 ID,而不需要进行疯狂排序。
可能需要使用 addSnapshotListened
,但我不明白如何使用。
更新代码:
for id in idsList {
dispatchGroup.enter()
Firestore.firestore().collection(...).document(id).getDocument{ (document, error) in
if let doc = document, doc.exists {
if let newHallModel = Halls(dictionary: doc.data()!, id: doc.documentID) {
self.tempHalls.append(newHallModel)
dispatchGroup.leave()
} else {
fatalError("Fatal error")
}
} else {
print("Document does not exist")
MBProgressHUD.hide(for: self.view, animated: true)
return
}
}
}
dispatchGroup.notify(queue: .global(qos: .default), execute: {
self.halls = self.tempHalls
DispatchQueue.main.async {
MBProgressHUD.hide(for: self.view, animated: true)
self.tableView.reloadData()
}
})
当您需要一个或多个您无法(基于您的数据架构)查询的文档时,应使用通过标识符获取文档。不要犹豫对数据进行非规范化以使查询正常工作,这就是 NoSQL 的意义所在。如果我是你,我会在这些文档中添加一个可以查询的字段,或者使用新集合(仅针对此查询)对该数据集进行非规范化。但是,如果您仍然选择通过标识符获取多个文档,那么您需要发出 n
getDocument
请求并使用调度组来处理异步:
let docIds = ["JtThFuT4qoK4TWJGtr3n", "TL1fOBgIlX5C7qcSShGu", "UkZq3Uul5etclKepRjJF"]
let d = DispatchGroup()
for id in docIds {
d.enter()
Firestore.firestore().collection(...).document(id).getDocument{ (document, error) in
// append to array
d.leave()
}
}
d.notify(queue: .global(), execute: {
// hand off to another array if this table is ever refreshed on the fly
DispatchQueue.main.async {
// reload table
}
})
调度组所做的就是记录它进入和离开的次数,当它们匹配时,它调用它的 notify(queue:execute:)
方法(它的完成处理程序)。
我遇到过同样的任务。并且没有更好的解决办法。一个一个抓取文件,所以写了个小扩展:
extension CollectionReference {
typealias MultiDocumentFetchCompletion = ([String: Result<[String: Any], Error>]) -> Void
class func fetchDocuments(with ids: [String], in collection: CollectionReference, completion:@escaping MultiDocumentFetchCompletion) -> Bool {
guard ids.count > 0, ids.count <= 50 else { return false }
var results = [String: Result<[String: Any], Error>]()
for documentId in ids {
collection.document(documentId).getDocument(completion: { (documentSnapshot, error) in
if let documentData = documentSnapshot?.data() {
results[documentId] = .success(documentData)
} else {
results[documentId] = .failure(NSError(domain: "FIRCollectionReference", code: 0, userInfo: nil))
}
if results.count == ids.count {
completion(results)
}
})
}
return true
}
}
与其逐一获取文档,
您可以使用“IN”查询通过 1 个请求获取 10 个文档:
userCollection.where('uid', 'in', ["1231","222","2131"]);
// or
myCollection.where(FieldPath.documentId(), 'in', ["123","456","789"]);
// previously it was
// myCollection.where(firestore.FieldPath.documentId(), 'in', ["123","456","789"]);
Firestore 文档:
“使用 in 运算符将同一字段上的最多 10 个相等 (==) 子句与逻辑 OR 组合在一起。in 查询 returns 给定字段与任何比较值匹配的文档”
Swift5 和 Combine:
func getRegisteredUsers(usersId: [String]) -> AnyPublisher<[RegisteredUser], Error> {
return Future<[RegisteredUser], Error> { promise in
self.db.collection("registeredUsers")
.whereField(FieldPath.documentID(), in: usersId)
.getDocuments { snapshot, error in
do {
let regUsers = try snapshot?.documents.compactMap {
try [=10=].data(as: RegisteredUser.self)
}
promise(.success(regUsers ?? []))
} catch {
promise(.failure(.default(description: error.localizedDescription)))
}
}
}
.eraseToAnyPublisher()
}
如何从 firestore 获取 ids 文档?
现在我从 backend 得到几个 ids 文档 我需要在 tableview[=80] 中显示收到的 ids 文档=].
在 firestore 我有这个 ids:
xNlguCptKllobZ9XD5m1
uKDbeWxn9llz52WbWj37
82s6W3so0RAKPZFzGyl6
EF6jhVgDr52MhOILAAwf
FXtsMKOTvlVhJjVCBFj8
JtThFuT4qoK4TWJGtr3n
TL1fOBgIlX5C7qcSShGu
UkZq3Uul5etclKepRjJF
aGzLEsEGjNA9nwc4VudD
dZp0qITGVlYUCFw0dS8C
n0zizZzw7WTLpXxcZNC6
例如我的 backend 只找到这个 ids:
JtThFuT4qoK4TWJGtr3n
TL1fOBgIlX5C7qcSShGu
UkZq3Uul5etclKepRjJF
或
aGzLEsEGjNA9nwc4VudD
dZp0qITGVlYUCFw0dS8C
n0zizZzw7WTLpXxcZNC6
我只需要在tableview中显示这三个id。 (但实际上后端 return 我有 100 多个 ID,下面你可以看到疯狂排序这些 ID)
后端 将此 id 添加到临时数组中 var tempIds: [String] = []
那么我如何才能从 firestore 获取那些 ID 并在 tableview 中显示它们?
我使用这个代码:
fileprivate func query(ids: String) {
Firestore.firestore().collection(...).document(ids).getDocument{ (document, error) in
if let doc = document, doc.exists {
if let newModel = Halls(dictionary: doc.data()!, id: doc.documentID) {
self.halls.append(newModel)
self.halls.shuffle()
self.halls.sort(by: { [=10=].priority > .priority })
self.tableView.reloadData()
} else {
fatalError("Fatal error")
}
} else {
return
}
}
}
我需要在后台处理来自 backend 的 ID,处理后需要在 tableview 中显示处理后的 ID,而不需要进行疯狂排序。
可能需要使用 addSnapshotListened
,但我不明白如何使用。
更新代码:
for id in idsList {
dispatchGroup.enter()
Firestore.firestore().collection(...).document(id).getDocument{ (document, error) in
if let doc = document, doc.exists {
if let newHallModel = Halls(dictionary: doc.data()!, id: doc.documentID) {
self.tempHalls.append(newHallModel)
dispatchGroup.leave()
} else {
fatalError("Fatal error")
}
} else {
print("Document does not exist")
MBProgressHUD.hide(for: self.view, animated: true)
return
}
}
}
dispatchGroup.notify(queue: .global(qos: .default), execute: {
self.halls = self.tempHalls
DispatchQueue.main.async {
MBProgressHUD.hide(for: self.view, animated: true)
self.tableView.reloadData()
}
})
当您需要一个或多个您无法(基于您的数据架构)查询的文档时,应使用通过标识符获取文档。不要犹豫对数据进行非规范化以使查询正常工作,这就是 NoSQL 的意义所在。如果我是你,我会在这些文档中添加一个可以查询的字段,或者使用新集合(仅针对此查询)对该数据集进行非规范化。但是,如果您仍然选择通过标识符获取多个文档,那么您需要发出 n
getDocument
请求并使用调度组来处理异步:
let docIds = ["JtThFuT4qoK4TWJGtr3n", "TL1fOBgIlX5C7qcSShGu", "UkZq3Uul5etclKepRjJF"]
let d = DispatchGroup()
for id in docIds {
d.enter()
Firestore.firestore().collection(...).document(id).getDocument{ (document, error) in
// append to array
d.leave()
}
}
d.notify(queue: .global(), execute: {
// hand off to another array if this table is ever refreshed on the fly
DispatchQueue.main.async {
// reload table
}
})
调度组所做的就是记录它进入和离开的次数,当它们匹配时,它调用它的 notify(queue:execute:)
方法(它的完成处理程序)。
我遇到过同样的任务。并且没有更好的解决办法。一个一个抓取文件,所以写了个小扩展:
extension CollectionReference {
typealias MultiDocumentFetchCompletion = ([String: Result<[String: Any], Error>]) -> Void
class func fetchDocuments(with ids: [String], in collection: CollectionReference, completion:@escaping MultiDocumentFetchCompletion) -> Bool {
guard ids.count > 0, ids.count <= 50 else { return false }
var results = [String: Result<[String: Any], Error>]()
for documentId in ids {
collection.document(documentId).getDocument(completion: { (documentSnapshot, error) in
if let documentData = documentSnapshot?.data() {
results[documentId] = .success(documentData)
} else {
results[documentId] = .failure(NSError(domain: "FIRCollectionReference", code: 0, userInfo: nil))
}
if results.count == ids.count {
completion(results)
}
})
}
return true
}
}
与其逐一获取文档, 您可以使用“IN”查询通过 1 个请求获取 10 个文档:
userCollection.where('uid', 'in', ["1231","222","2131"]);
// or
myCollection.where(FieldPath.documentId(), 'in', ["123","456","789"]);
// previously it was
// myCollection.where(firestore.FieldPath.documentId(), 'in', ["123","456","789"]);
Firestore 文档: “使用 in 运算符将同一字段上的最多 10 个相等 (==) 子句与逻辑 OR 组合在一起。in 查询 returns 给定字段与任何比较值匹配的文档”
Swift5 和 Combine:
func getRegisteredUsers(usersId: [String]) -> AnyPublisher<[RegisteredUser], Error> {
return Future<[RegisteredUser], Error> { promise in
self.db.collection("registeredUsers")
.whereField(FieldPath.documentID(), in: usersId)
.getDocuments { snapshot, error in
do {
let regUsers = try snapshot?.documents.compactMap {
try [=10=].data(as: RegisteredUser.self)
}
promise(.success(regUsers ?? []))
} catch {
promise(.failure(.default(description: error.localizedDescription)))
}
}
}
.eraseToAnyPublisher()
}