Я создаю приложение, в котором пользователи могут публиковать изображения кошек, а другим пользователям могут «нравиться» эти изображения.
Мне нужно иметь возможность запрашивать наиболее понравившиеся изображения, а также запрашивать изображениякоторый понравился конкретному пользователю.
Я пытаюсь решить, как моделировать «похожие» данные.В частности, есть следующие опции:
Хранить лайки внутри фотографии кошки в виде карты.как:
//cats:
{
likes: {
[userId: string]: {
user: {
id: string,
displayName: string,
profilePhoto: string
},
createTime: Date
}
},
nLikes: number
}
Хранить лайки внутри документа фотографии кота в виде массива, а пользовательские данные в виде неиндексированной карты, например:
//cats
{
...
likeIds: string[], // userIds
likeUsers: { // <- unindexed
[userId: string]: ...
}
}
Создайте новую коллекцию верхнего уровня /likes
, имеющую ссылку catId
.
Я думаю, так как я чаще всего захочу получить вселайки для определенной картинки (и показывать имена пользователей и фотографии профиля людей, которым понравилась картинка), использование карты (вариант 1) имеет смысл.Это также упрощает мои запросы, поскольку я могу сказать что-то вроде:
db.collection('cats').where(`likes.${userId}.user.id`, '==', userId)
, чтобы получить все документы cat, которые понравились данному пользователю.
С другой стороныИтак, после прочтения этих ограничений на индексы я обеспокоен тем, как приведенная выше карта userId
будет взаимодействовать с индексированием.Поскольку в документах моей коллекции будет присутствовать много разных записей userId
(на самом деле, порядка миллионов, если мой сайт обмена фотографиями cat будет успешным).Похоже, что он очень быстро достигнет предела индекса, так как я предполагаю, что индекс создается для каждого уникального значения ключа в любом документе в коллекции.
Вариант 2 позволяет использовать array-contains
запросов для поиска кошекнравится определенным пользователям.Но я не знаю, отличаются ли массивы и карты тем, как они взаимодействуют с индексами.Представляется столь же вероятным, что внутренне Firestore превращает массив в карту {[userId: string]: true}
, которая будет иметь ту же проблему с индексированием, что и опция 1.
Наконец, использование опции 3 (коллекция верхнего уровня /likes
) будетопределенно будьте в безопасности для размера индекса и позвольте мне запрашивать информацию понятным способом.Однако это, кажется, идет вразрез с философией Firestore о денормализации данных для оптимизации операций чтения.Для моих самых популярных картинок кошек (те, которые, вероятно, понравятся тысячам пользователей и просматриваются миллионами каждый день), мне теперь нужно будет сделать много чтений, чтобы получить информацию о людях, которым понравилась фотография, стоимостью$$$ и прекращение работы моего приложения для обмена фотографиями с кошками.
Итак, чтобы подвести итог, законны ли мои опасения по поводу плохого взаимодействия с индексами в вариантах 1 и 2?Исключают ли они эти стратегии как жизнеспособные, если число пользовательских идентификаторов (по всем документам в коллекции) становится большим?Я вынужден использовать вариант 3 в этой ситуации, даже несмотря на увеличение числа операций чтения / затрат на работу приложения?
Спасибо!