FireStore getDocuments () Функция работает очень медленно при первом поиске запроса - PullRequest
0 голосов
/ 19 апреля 2020

Фон

Я использую Firebase Firestore для получения данных Engli sh слов, используя функцию 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]

Если это предложение никогда не было найдено, запрос буквально займет 30 с . Этот номер получен из print("First: \(self.first! - self.start!)"). Если я снова буду искать эту же вещь, это займет максимум 1s . Это происходит с любым поиском, независимо от того, большой он или маленький. Я провел некоторое исследование и обнаружил, что некоторые люди упоминали что-то о времени холодного запуска облачной функции, а также у других были подобные проблемы, но я не смог найти качественного решения для решения этой проблемы. Я попытался отключить постоянство settings.isPersistenceEnabled = true, но это не сработало. Есть ли решение? Я что-то неправильно внедряю или это проблема с Firestore. Любая помощь или совет высоко ценится. Спасибо!

1 Ответ

0 голосов
/ 23 апреля 2020

В итоге я просто извлек каждый из документов по отдельности, используя getDocument() вместо предложения where, и с помощью группы рассылки, чтобы сообщить мне, когда все запросы завершены.

    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)")
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...