Недавно поигрался с Геохеши и Firestore. Мой сценарий задачи состоит в том, чтобы иметь коллекцию документов (рестораны), и каждый ресторан будет иметь список геохешей, в которые доставляется.
Я хочу избежать добавления гео-сшивки в ресторане документов, так как документ может быть во много раз больше, чем должен быть.
Первоначальная идея состоит в том, чтобы иметь все геохеши в подколлекции документа ресторана, но я обнаружил, что невозможно выполнять запросы в подколлекции документов.
Вторая идея заключалась в том, чтобы извлечь геохеши на верхний уровень в коллекции областей доставки.
document:{ restaurantName: "aRestaurant",
deliveryArea: Arraylist<String> }
Проблема в этом сценарии заключается в том, что я верну список названий ресторанов, где затем мне нужно будет запросить коллекцию ресторанов, чтобы получить их, и, насколько мне известно, я не могу выполнять операции ИЛИ в запросах.
Я впервые играю с базами данных документов и Firestore. Будем очень признательны за любое руководство.

I want to avoid adding the geoashes in the document restaurant as the document can be many times bigger than it should be.
Да, не делайте этого, потому что у документов есть ограничения. Таким образом, есть некоторые ограничения, когда речь идет о том, сколько данных вы можете поместить в документ. Согласно официальной документации относительно использование и ограничения:
Maximum size for a document: 1 MiB (1,048,576 bytes)
Как видите, общий объем данных в одном документе ограничен 1 МБ. Когда мы говорим о хранении текста, вы можете хранить довольно много, но если вы используете сложные объекты, это не вариант.
The initial idea is to have all of the geohashes in a subcollection of the restaurant document but I found out its not possible to perform queries in subcollection of documents.
Это хорошее решение. Структура вашей базы данных должна выглядеть так:
Firestore-root
|
--- restaurants (collection)
|
--- restaurantId (document)
|
--- geohashes (collection)
|
--- geohashId (document)
|
--- //details about the location
Таким образом, запрос, который может позволить вам получить все объекты geohash конкретного ресторана, будет работать отлично.
The second idea was to extract the geohashes to top level in a collection of delivery areas
Это неплохое решение, но вы должны создать дополнительный вызов get(), чтобы получить информацию о ресторане, но даже если это сделать, это неплохой вызов, нет проблем с вложенными запросами в Firestore. Нет необходимости в эксплуатации OR.
Редактировать: Согласно вашему комментарию, да, вы правы, вы не можете запросить базу данных, чтобы вернуть объекты ресторана, но у нас тоже есть работа. В этом случае вам следует подумать о расширении своей структуры данных, чтобы разрешить обратный поиск, добавив новую коллекцию, подобную этой:
Firestore-root
|
--- geohashes (collection)
|
--- geohashId (document)
|
--- geohashRestaurants (collection)
|
--- restaurantId
|
--- //restaurant details
Этот метод называется denormalization, что, как видите, подразумевает дублирование данных. Но вы должны знать, что в Firebase нет проблем с дублированием данных. Это довольно распространенная практика, и для этого я рекомендую вам посмотреть это видео, Денормализация - это нормально с базой данных Firebase. Предназначен для базы данных Firebase в реальном времени, но тот же принцип применим и к Cloud Firestore.
Когда вы дублируете данные, нужно иметь в виду одну вещь. Так же, как вы добавляете данные, вам необходимо их поддерживать. Другими словами, если вы хотите обновить / определить элемент, вам нужно сделать это везде, где он существует.
Огнебазер здесь
Наша оригинальная библиотека GeoFire для базы данных Firebase Realtime решила именно эту проблему, имея отдельный узел верхнего уровня для геохешей. Каждый ключ под этим узлом обычно соответствует ключу фактического объекта в другом узле верхнего уровня.
Так что-то вроде:
locations
key1: { g: "sa7ads", l: [ 14.5232, -156.17843 ] },
key2: { g: "fds347", l: [ -127.172, 167.1324 ] }
restaurants
key1: { name: "This is the first restaurant", ... },
key2: { name: "This is the second restaurant", ... },
С помощью этой структуры вы выполняете гео-запрос на /locations, а затем читаете дополнительную информацию о каждом ресторане в диапазоне от /restaurants/$key. Это неплохо масштабировалось.
Я бы рекомендовал такой же подход с Cloud Firestore. У вас будет две коллекции верхнего уровня: одна с (меньшими) данными о местоположении, а другая с (большими) дополнительными данными о каждом ресторане. Это уменьшает объем данных, которые вы читаете, хотя в конечном итоге вы прочитаете больше документов. Вам нужно будет сбалансировать эти два параметра (пропускная способность и количество чтений документов) друг против друга.
Несколько месяцев назад я дал поговорить о выполнении гео-запросов в Cloud Firestore, который, возможно, стоит проверить.
Привет, Фрэнк, ваш разговор был потрясающим! Я заглянул в библиотеку GeoFire и выглядит действительно хорошо. Хотя это один из вопросов, который возник во время просмотра вашего выступления, что произойдет, если, например, один из ресторанов захочет изменить место доставки? Вам нужно будет получить все документы (геохеши), которые его содержат, изменить и сохранить. Звучит как большая операция для бессерверной инфраструктуры: / (думаю, в этой ситуации может пригодиться облачная функция)
Спасибо, Алекс, за подтверждения. Теперь большой вопрос в том, что если я последую какой-либо из этих идей, я не смогу запросить геохеши (коллекцию), чтобы вернуть ресторан (документы). `db.collection (Restaurants) .get (). where (geohash == ABCD123)` Вышеупомянутый запрос - это то, что мне нужно, и, к сожалению, подгруппа запросов недоступна в firestore. :(