У меня есть некоторые опасения по поводу структуры проекта на основе Firestore, поскольку прямое вложение документов не представляется возможным.
Для простоты предположим, что у нас есть база данных firestore, содержащая данные о футбольных матчах. Для каждого матча есть документ с составом игроков, документ со списком событий матча, документ со статистикой матча и т. д.
Поскольку такие вещи, как статистика, события и составы, обновляются через разные промежутки времени, импортируются из разных вызовов API и используются на отдельных экранах в приложении-потребителе, я думаю, будет разумнее хранить их в отдельных документах.
В настоящее время я использую такую структуру:
/app-data/match-lineup/matches/123456
/app-data/match-events/matches/123456
/app-data/match-statistics/matches/123456
И тогда я обращаюсь к этому так:
db.collection("app-data")
.doc("match-lineups")
.collection("matches")
.doc(id);
Но по мере того, как я добавляю больше разных документов, связанных с совпадением, у меня возникают опасения, не является ли текущая структура анти-шаблоном.
Я бы предпочел подобную структуру, которую я считаю наиболее элегантной и похожей на URL-адрес REST.
/matches/123456/lineup
Но это не вариант, поскольку 123456
не может ссылаться на lineup
документ.
Обходной путь может быть чем-то вроде
/matches/123456/attributes/lineup
С такой ссылкой
db.collection("matches")
.doc(id);
.collection("attributes")
.doc("lineup")
Это лучший компромисс, или есть другие варианты, которые следует рассмотреть?
Никогда не бывает решения лучший и уникальный при моделировании данных в базе данных NoSQL.
ИМХО, ваши два подхода полностью действительны, поскольку данные, содержащиеся в каждой коллекции, будут «использоваться на отдельных экранах в приложении-потребителе» (т.е. нет причин «концентрировать» все данные в одном документе, как вы упоминаете ). С точки зрения эффективности запросов эти два подхода схожи.
Однако есть еще один критерий, который вы можете принять во внимание: (на момент написания) вы не можете запрашивать по коллекциям. Вы можете столкнуться с вариантом использования, когда вам нужно запросить матчи, например, все матчи с определенным игроком в составе или все матчи с eventType == "penalty"
. В этом случае вам следует использовать подход №1 (т. е. /app-data/match-lineup/matches/123456
), так как такие запросы по совпадениям будут невозможны при подходе №2.
Спасибо за ваш ответ. Я рад слышать, что я на правильном пути. Документы, которые я создаю, объединяются как из пользовательских данных, так и из данных API, и я не ожидаю делать какие-либо запросы к этим документам, которые передают содержимое экранов в приложении. Тогда я выберу тот, который выглядит лучше :)
@EsbenvonBuchwald Рад, что смог помочь! :-). Вы можете подтвердить и/или принять ответ, если «вы считаете, что это лучшее решение вашей проблемы», см. stackoverflow.com/help/someone-answers. Спасибо!
Я не думаю, что стоит думать о структурах данных Firestore как об «элегантных» или нет. Пути также не обязаны выглядеть как REST API. В первую очередь нужно учитывать, соответствует ли структура запросам, которые вы собираетесь делать. У вас может быть «элегантная» структура, но она полностью не соответствует потребностям вашего приложения. Сначала подумайте о потребностях вашего приложения, а затем о структуре, соответствующей этим потребностям.