swift 获取几个ids文档firestore

p4tfgftt  于 2023-05-16  发布在  Swift
关注(0)|答案(4)|浏览(126)

如何从firestore获取id文档
现在我从backend得到了几个ids文档,需要在tableview中显示收到的ids文档。
firestore我有这个id
xNlguCptKllobZ9XD5m1uKDbeWxn9llz52WbWj3782s6W3so0RAKPZFzGyl6EF6jhVgDr52MhOILAAwfFXtsMKOTvlVhJjVCBFj8JtThFuT4qoK4TWJGtr3nTL1fOBgIlX5C7qcSShGuUkZq3Uul5etclKepRjJFaGzLEsEGjNA9nwc4VudDdZp0qITGVlYUCFw0dS8Cn0zizZzw7WTLpXxcZNC6
比如我的后台只找到这个id
JtThFuT4qoK4TWJGtr3nTL1fOBgIlX5C7qcSShGuUkZq3Uul5etclKepRjJF

aGzLEsEGjNA9nwc4VudDdZp0qITGVlYUCFw0dS8Cn0zizZzw7WTLpXxcZNC6
我只需要在tableview中显示这三个id。(但实际上后端返回我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: { $0.priority > $1.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()
                            }
                        })

ogq8wdun

ogq8wdun1#

你可以使用“IN”查询,而不是一个接一个地获取文档,你可以用一个请求获取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运算符可以在同一字段上用逻辑OR合并最多10个相等(==)子句。in查询返回给定字段与任何比较值匹配的文档”

cgh8pdjw

cgh8pdjw2#

当您需要一个或多个无法查询的文档时,应使用通过其标识符获取文档。不要犹豫去非规范化你的数据以使查询工作,这就是NoSQL的重点。如果我是你,我要么向这些文档添加一个字段,以便可以查询它们,要么用一个新的集合(仅用于此查询)将此数据集反规范化。但是,如果您仍然选择通过标识符获取多个文档,那么您需要发出ngetDocument请求,并使用调度组来处理它们的同步。

let docIds = ["JtThFuT4qoK4TWJGtr3n", "TL1fOBgIlX5C7qcSShGu", "UkZq3Uul5etclKepRjJF"]
let d = DispatchGroup()
    
for id in docIds {
    d.enter()
    
    Firestore.firestore().collection(...).document(id).getDocument { (document, error) in
        // handle doc
        d.leave() // always leave no matter how you exit this closure
    }
}

d.notify(queue: .main, execute: {
    // here is your completion when the last leave() was called
})

调度组所做的就是记录它进入和离开的次数,当它们匹配时,它调用它的notify(queue:execute:)方法(它的完成处理程序)。

h22fl7wq

h22fl7wq3#

我也面临过同样的任务。没有更好的解决方案。一个接一个地获取文档,所以我写了一个小扩展:

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
}
}
bybem2ql

bybem2ql4#

Swift5和合并:

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 $0.data(as: RegisteredUser.self)
                    }
                    
                    promise(.success(regUsers ?? []))
                } catch {
                    promise(.failure(.default(description: error.localizedDescription)))
                }
            
        }
    }
    .eraseToAnyPublisher()
}

相关问题