Firestore: Как спроектировать модель данных, чтобы сделать возможным запрос документов, которых нет в массиве? - PullRequest
0 голосов
/ 18 января 2019

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

Итак, я получил что-то вроде:

  • У пользователя User1 есть массив "встреченных людей"
  • A «Еще не встретил пользователя» / User2 его также пользователь с той же моделью документа
  • Все они принадлежат к одной коллекции "Users"
  • Я хочу опросить всех пользователей, которые еще не провели этот пользователь1

Я знаю, что вы не можете делать что-то вроде "array_not_contains" или "! =", Потому что все поля, которые вы запрашиваете, должны быть проиндексированы.

Итак, мне интересно, возможно ли моделировать данные, чтобы они работали, или единственное решение - удалить Firebase, потому что этот тип запроса вообще невозможен?

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

EDIT:

Еще раз спасибо за ваш ответ и извините за мой поздний ответ.

Нет необходимости создавать новый вызов базы данных, поскольку вы уже получили всех пользователей из этой области.

Нет Если у меня установлен большой отклик, я ограничусь числом. (5 в примере ниже). И даже если я не ограничу число, в следующем вызове БД я узнаю, что были добавлены новые люди, и как получить только их.
Я не буду удалять их из Коллекции пользователей, если они могут быть показаны другим пользователям.

P.S: Я забыл User4 в фотографиях из коллекции пользователей.

Initial db state

Для пользователя 1: получить 5 первых совпадений, удалить существующие, показать пользователя 5.
Для User2: получить 5 первых совпадений, удалить существующие, показать User4, User5.
После выбора пользователей, пользователи добавляются в их список. Коллекция пользователей осталась прежней.

step 2

Для пользователя 1 получите 5 первых совпадений, удалите существующие, нечего показывать, даже если у меня есть пользователь 6, 7.
Чтобы исправить это, я запускаю второй запрос, получаю новые, но чем больше пользователь использует приложение, тем больше запросов мне может понадобиться, чтобы попытаться показать ему существующего пользователя в его области.

Может быть, я неправильно понял то, что вы назвали «начальный список», для меня это объект списка, извлеченный из моей базы данных, содержащий всех пользователей (с ограничением).

РЕДАКТИРОВАТЬ 2:

Вы можете проверить ответы Алекс Мамо , чтобы узнать, как запрашивать документы, которых нет в массиве.

Позвольте мне объяснить мой вариант использования и почему я думаю, что это не сработает.

Я хочу иметь возможность искать всех пользователей рядом со мной, пытается сделать это в Firebase, я храню Geopoint. На данный момент Geopoint нельзя реально использовать из коробки с Firebase, поэтому я использую Geofirestore в облачной функции.
Я сохраняю и обновляю геопоинты пользователей в зависимости от их местоположения, поэтому это означает, что местоположение пользователя изменяется по времени . Я ограничиваю количество пользователей, возвращаемых этой функцией.

initial search

В исходном состоянии я получаю пользователей рядом со мной (User1), я получаю 3 и 4.
Допустим, я сохраняю последний проверенный userId, чтобы позже использовать его в качестве курсора для моего запроса (пользователь 4).

Теперь моя геопозиция меняется, и пользователи в этой области тоже меняются. Я запрашиваю следующую группу пользователей рядом со мной и использую свой предыдущий userId / document для «startAfter» (подробнее об этом
здесь ), смотрите изображение ниже, это не сработает.

second search

Если я использую курсор (User4), я возьму 5, но не 2, потому что в списке возврата, если я упорядочу по Id, 2 будет раньше 4.
Хуже того, как показано ниже, если в списке возврата может даже не быть пользователя 4, курсор будет бессмысленным.

thirdsearch

Мой пример немного упрощен и не учитывает то, что описано в первом ответе и моем первом редактировании (ограниченное подмножество пользователей, дизайн данных).

1 Ответ

0 голосов
/ 18 января 2019

Возможная структура базы данных для вашего приложения:

Firestore-root
    |
    --- users (collection)
         |
         --- uid (document)
              |
              --- acceptedUsers: ["uidOne", "uidTwo"]
              |
              --- declinedUsers: ["uidThree", "uidFour"]
              |
              --- //Other user properties

Механизм прост. Когда вы впервые захотите показать профиль пользователя текущему (прошедшему проверку подлинности) пользователю, вы должны создать запрос, который будет возвращать всех пользователей (в пользовательской области). В соответствии с решением пользователя, вам необходимо добавить соответствующий uid либо в массиве acceptedUsers, либо в массиве declinedUsers. Если вы хотите показать других пользователей, используйте тот же запрос, но на этот раз вам нужно будет выполнить дополнительную операцию. Как только запрос вернет пользователей в пределах их местоположения, добавьте всех этих пользователей в список. Сравните список, поступающий из базы данных, с существующими массивами и удалите всех пользователей из обоих массивов. Таким образом, у вас будет список, содержащий только пользователей, которых фактический пользователь не видел. Этот дополнительный шаг необходим, чтобы убедиться, что идентификатор пользователя не существует в одном из этих массивов. В конце просто выберите случайного пользователя из списка и покажите детали пользователю. Вот и все!

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

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

Edit:

Давайте рассмотрим первоначальный список пользователей, который имеет 10 записей. Другими словами, все пользователи в этой области - 10. Вы говорите, что 7 пользователей уже видели, что делает список содержит только 3 оставшихся пользователей.

Итак, я отображаю 3 (или делаю еще один запрос, чтобы получить больше), и он проверяет 3.

Да, вы должны отобразить этих 3 пользователей, а затем удалить их одного за другим из первоначального списка. Нет необходимости создавать новый вызов базы данных, поскольку вы уже получили всех пользователей из этой области. Как только список останется пустым, вы должны отобразить сообщение для пользователя, что в этой конкретной области больше нет пользователей, чтобы провести пальцем.

Когда будет создан еще один вызов базы данных?

Только при необходимости. Это означает, что вы создаете еще один вызов, когда новые пользователи входят в эту область. Допустим, 3 новых пользователя являются новыми, теперь вы получаете список из 3 пользователей и используете тот же алгоритм.

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

Если вы считаете, что массивы будут расти больше, чем может вместить документ, вам следует рассмотреть вопрос о сохранении пользователей в коллекции, а не в массиве. Так что в этом случае проблема заключается в том, что документы имеют ограничения. Таким образом, существуют некоторые ограничения в отношении объема данных, которые вы можете поместить в документ. Согласно официальной документации относительно использования и ограничений :

Максимальный размер документа: 1 МБ (1 048 576 байт)

Как видите, вы ограничены 1 МБ данных в одном документе. Когда мы говорим о хранении текста (uids), вы можете хранить довольно много, но по мере увеличения массива будьте осторожны с этим ограничением.

Но если вы будете оставаться в этих пределах, что я лично считаю, вам не о чем беспокоиться.

Edit2:

Нет Если у меня установлен большой отклик, я ограничусь числом. (5 в примере ниже). И даже если я не ограничу количество, в следующем вызове БД, как я могу узнать, что новые люди были добавлены и как получить только те. Я не буду удалять их из Коллекции пользователей, если они могут быть показаны другим пользователям.

Если у вас большой объем данных (много пользователей в одной области), да, это хорошая идея, чтобы ограничить результаты, но гораздо лучше было бы загружать данные небольшими порциями. Короче говоря, получите 5 пользователей, удалите одного за другим, пока в списке не будет нулевых пользователей, загрузите других 5 пользователей и так далее. Это можно сделать, используя мой ответ из следующего поста:

Начальный список - это список, который вы получаете, когда вы впервые запрашиваете базу данных. В этом случае первоначальный список будет содержать 5 пользователей.

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