ios - FireStore getDocuments() 函数在第一次搜索查询时运行速度极慢
问题描述
背景
我正在使用 Firebase Firestore 使用该getDocuments()
功能检索英文单词数据。这是检索数据的数据模型。
struct WordModel: Codable {
let id: String
let number: Int
var partOfSpeech: [String]?
var ipa: [String?]
var audio: [String?]
private enum CodingKeys: String, CodingKey {
case id
case number
case partOfSpeech
case ipa
case audio
}
}
查询是一个单词或句子,它被分解为一个单词数组,其中每个单词数组的块大小最多为 10。然后我使用.whereField("id", in: wordChunk)
来查询这些单词。wordChunk 是一个最多包含 10 个单词的数组。这是运行查询并返回结果的函数:
func readEnglishDocumentByWord(words: [String], completion: @escaping(_ result: [WordModel?]) -> Void) {
var results = [WordModel?]()
var finalResult = [WordModel?]()
var data: WordModel?
let lowerCaseWords = words.map { $0.lowercased() }
let wordChunks = lowerCaseWords.chunked(into: 10)
start = CFAbsoluteTimeGetCurrent() //start timer
for wordChunk in wordChunks {
let docRefs = db.collection(K.FBConstants.dictionaryCollectionName).whereField("id", in: wordChunk)
docRefs.getDocuments { (querySnapshot, err) in
self.first = CFAbsoluteTimeGetCurrent() // first time check
print("First: \(self.first! - self.start!)")
if let err = err {
print("Error getting documents: \(err)")
completion(finalResult)
} else {
for document in querySnapshot!.documents {
do {
data = try document.data(as: WordModel.self)
results.append(data)
} catch {
results.append(nil)
}
}
for word in words {
let tempWordModel = results.filter { $0?.id == word.lowercased() }
if tempWordModel.count == 0 {finalResult.append(nil)}
else {finalResult.append(tempWordModel[0])}
}
}
completion(finalResult)
}
}
}
问题
假设我搜索句子:“今天将是美好的一天”
这意味着wordChunk = [today, will, be, a, good, day]
如果以前从未搜索过这句话,则查询将花费30s。这个号码是从 中检索的print("First: \(self.first! - self.start!)")
。如果我再次搜索同样的东西,最多需要1s。这发生在任何搜索中,无论大小。我做了一些研究,发现有些人提到了有关云功能冷启动时间的内容,以及其他人有类似问题,但我无法找到解决此问题的优质解决方案。我尝试禁用持久性settings.isPersistenceEnabled = true
,但没有奏效。有解决办法吗?我是在错误地实现某些东西还是 Firestore 的问题。非常感谢任何帮助或建议。谢谢!
解决方案
我最终只是使用而不是使用 where 子句单独拉出每个文档getDocument()
,并使用 Dispatch 组来告诉我所有查询何时完成。
func readEnglishDocumentByWord(words: [String], completion: @escaping(_ result: [WordModel?]) -> Void) {
var results = [WordModel?]()
var finalResults = [WordModel?]()
let lowerCaseWords = words.map { $0.lowercased() }
let dispatchGroup = DispatchGroup()
start = CFAbsoluteTimeGetCurrent() //start timer
for word in lowerCaseWords {
let docRef = db.collection(K.FBConstants.dictionaryCollectionName).document(word)
dispatchGroup.enter()
docRef.getDocument { (document, error) in
self.first = CFAbsoluteTimeGetCurrent() // first time check
print("First: \(self.first! - self.start!)")
let result = Result {
try document.flatMap {
try $0.data(as: WordModel.self)
}
}
switch result {
case .success(let wordModel):
if let wordModel = wordModel {
results.append(wordModel)
} else {
results.append(nil)
print("Document does not exist")
}
case .failure(let error):
results.append(nil)
print("Error decoding city: \(error)")
}
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .main) {
for word in words {
let temp = results.filter{$0?.id == word.lowercased()}
if temp.count == 0 {finalResults.append(nil)}
else {
finalResults.append(temp[0])
}
}
completion(finalResults)
print("Finished with results: \(results.count)")
}
}
推荐阅读
- c++ - 关于 intel x86_64 了解何时将多个线程访问的内存按 128 字节和 64 字节进行分区
- javascript - 有没有更简单的方法来使用 jQuery 显示和隐藏许多 div?
- json - 在 zip 文件夹中编辑 .json 文件,无需解压缩
- java - 为什么即使在机器上运行多个 java 应用程序时也没有 JMX 冲突?
- java - Java AtomicReference#getAndSet 的用例是什么?
- vbscript - 需要通过 VBScript 重命名特定文件夹中的多个文件
- java - AdapterPost.java 中的“java.lang.NumberFormatException:null”错误
- regex - 为什么我不能在 PowerShell 的替换运算符中转换匹配标记?
- macos - 在 Mac Catalina 中运行可执行文件时出错
- javascript - 从受 SSL 保护的 HTTPS React JS Web 应用程序连接本地连接的打印机