Составной запрос iOS Firestore с несколькими идентификаторами - PullRequest
0 голосов
/ 27 ноября 2018

Это проблема, с которой я столкнулся, пытаясь смешать географическое местоположение с Firestore.Короче говоря - мне нужны рестораны вокруг местоположения пользователя.Для того, чтобы выполнить гео-поиск, я использую Algolia.Когда я делаю запрос к Algolia, он возвращает массив уникальных идентификаторов ресторана, которые соответствуют идентификаторам документов Firestore.Это прекрасно работает.

Что усложняет то, что мне нужно еще два условия - мне нужно ограничить запрос ресторанами со средним рейтингом> = 8. А также я хочу ограничить количество возвращаемых документов.(2, 5, 20 и т. Д.).

Вот так это должно выглядеть в псевдокоде:

db.restaurantsCollection
    .documentIds([111, 222, 333, 444, 555, 666, 777, 888, 999])
    .whereField("averageRating", isGreaterThanOrEqualTo: 8)
    .order(by: "averageRating", descending: true)
    .limit(to: 2)
    .getDocuments()

Я знаю, что на сегодняшний день Firestore не поддерживает запросы с несколькими идентификаторами документов.Итак, что является наиболее оптимизированным способом выполнения такого запроса?

Если я установлю documentId в качестве поля id в своем документе, а затем переберу все возвращенные идентификаторы из Algolia и сделаю что-то вродеэто (тогда я могу сделать упорядочивание и ограничение в чистом Swift):

for id in ids {
    db.restaurantsCollection
        .whereField("averageRating", isGreaterThanOrEqualTo: 8)
        .whereField("id", isEqualTo: id)
        .getDocuments()
}

Но все же это означает много запросов.Есть другие идеи?

1 Ответ

0 голосов
/ 25 июля 2019

В случае, если это будет полезно всем, я публикую опцию, которую вы могли бы рассмотреть, если вы реализуете гео-запросы так, как я их реализовал - с помощью Algolia.Таким образом, способ, которым вы делаете это с Алголией, состоит в том, чтобы сохранять координаты с вашими поисковыми индексами.

Например:

{
  "_geoloc": {
    "lng": 8.507785799999999,
    "lat": 47.17652589999999
  },
  "objectID": "1234abcd"
}

Где objectID соответствует идентификатору документа ресторана или любого типа места, к которому вы хотите выполнить гео-запрос.

Затем вы создаете запросчерез Algolia API.Если вы хотите получить все элементы вокруг CLLocation, вы должны настроить его - используйте для этого свойство query.aroundLatLng.Вы также можете установить свойство distance в метрах.Результатом будет JSON с вашими идентификаторами, отсортированными по их расстоянию, начиная с ближайшего.

Пока все хорошо - мы решили нашу самую большую проблему - запрос по географическому местоположению.

Теперь, что если яхотите получить самый высокий рейтинг из всех N ID, которые я получил от Алголии?Печально то, что до сих пор нет API для запроса по нескольким идентификаторам.Таким образом, это означает, что если я хочу получить все рестораны с показателем> = 8, мне нужно сделать так, чтобы документ N Firestore прочитал, а затем получил рейтинг с наибольшим рейтингом.Далеко от идеала.

Вариант 1.

Сохранение средних значений по ресторану с данными по Алголии.

Я знаю, что это означает дополнительные сетевые возможности, но это хороший путь.Недостатки - каждый раз, когда вы обновляете среднее значение ресторана в Firestore, вам также необходимо обновлять его в Algolia.И если вы вычисляете средние значения с помощью облачных функций, как я, вам нужно установить их и в Алголии.Да, это означает, что вам нужно перейти на платный тарифный план Firebase, поскольку это внешний вызов Cloud Functions.

Теперь, когда у вас есть средние значения в полезной нагрузке Algolia, вы можете легко получить все идентификаторы ресторанов для своего региона, а затем отсортироватьданные по клиентской части рейтинга Algolia.После сортировки идентификаторов вы можете запросить документы в Firestore.

Вариант 2.

Сохранить название города и страны

Вы можете сохранить названия городов и стран с помощью своегоРасположение данных в Firestore.Таким образом, вы можете использовать их для ваших запросов.Код запроса Pseudo Firestore:

db.restaurants.where("city" == "current_city").where("country" == "current_country").where("averageRating" >= 8).getDocuments()

Однако этот подход не будет очень точным и в основном будет работать для больших городов.Также не учитывается близость к вашему местоположению.

Надеюсь, это поможет.

...