Есть ли лучший способ оптимизировать этот запрос Firestore? - PullRequest
0 голосов
/ 11 июня 2019

Сейчас я запрашиваю массивы Firestore на основе другого массива строк. Это прекрасно работает, но я хотел бы знать, правильно ли это, и есть ли способ оптимизировать его, чтобы сделать его быстрее.

Вот мой код.

var exampleArray = [test]()

func loadData(textArray : [String]){
        let db = Firestore.firestore()

        for i in 0..<textArray.count{
            db.collection("testCollection").whereField("testField", arrayContains: textArray[i]).getDocuments{ (querySnapshot, err) in
                if let err = err {
                    print("\(err.localizedDescription)")
                    print("Test Error")
                } else {
                    if (querySnapshot!.isEmpty == false){
                        let res = querySnapshot!.documents.compactMap({test(dictionary: $0.data())})
                        self.exampleArray.append(contentsOf: res)
                        self.summaryTableView.reloadData()
                        SVProgressHUD.dismiss()
                        print(self.textArray[i])

                    }
                }
            }
        }
    }

Заранее спасибо.

UPDATE:

Некоторая информация:

  • Сейчас процесс и запрос VisionCloudRecognition занимают около 10-11 секунд. 7 секунд распознавания и 3-4 запроса.
  • В базе данных 7700 документов по 7 полей в каждом.

В основном мое приложение выполняет следующие действия:

  • Пользователь делает фотографию
  • С OCR изображение становится текстом, и я добавляю текст в массив строк. Мы не знаем, сколько будет строк. Может быть 0 или 50.
  • Затем я запрашиваю массивы Firestore на основе массива строк.

1 Ответ

3 голосов
/ 11 июня 2019

Как отмечено в комментариях, вы выполняете несколько асинхронных запросов в цикле (это всегда плохо) и перезагружаете данные, когда каждый из них разрешается, в результате чего tableView продолжает перерисовывать с новыми данными.

То, что вы хотите сделать, это добавить все эти запросы к базе данных в DispatchGroup. Когда они разрешатся, добавьте данные в ваш массив. Как только они все закончили, сделайте один tableView.reloadData() и отклоните ваш SVProgressHud.

Это должно не только ускорить процесс, потому что несколько вызовов могут происходить параллельно, но у вашего пользователя не будет подпрыгивания строк таблицы при добавлении новых данных, и tableView перезагружает X раз в быстром режиме.

РЕДАКТИРОВАТЬ: Вы попросили пример - это очень быстро и написано здесь, на SO, поэтому ищите XCode, чтобы уведомить вас о любых опечатках или ошибках.

class MyVC: UIViewController {

  var exampleArray = [test]()
  let db = Firestore.firestore()
  let dispatchGroup = DispatchGroup()

  override func viewDidLoad(animated: bool) {
    super.viewDidLoad(animated)

    myTableView.delegate = self
    myTableView.dataSource = self

    for i in 0..<textArray.count {
      getTestFieldRecords(i)
    }

    dispatchGroup.notify(queue: .main) {
      self.myTableView.reloadData()
    }
  }

  private func getTestFieldRecords(_ record: Int) {
    dispatchGroup.enter()
    db.collection("testCollection").whereField("testField", arrayContains: textArray[i]).getDocuments{ (querySnapshot, err) in
      if let err = err {
        print("\(err.localizedDescription)")
        print("Test Error")
      } else {
        // rest of your code because I'm too lazy to format it
      }
      self.dispatchGroup.leave()
    }
  }

}

Обязательно звоните leave() каждый раз - ошибка или нет. DispatchGroup не завершится, пока все команды enter() не будут завершены командой leave(). Надеюсь, это поможет вам в правильном направлении!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...