Рефакторинг схемы вложенных коллекций Firestore - PullRequest
0 голосов
/ 10 мая 2019

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

// {} signifies a collection

{Ships}
  001
  {Voyages}
    voy1
    {Logs}
      12:01 This was all good
      12:11 Things are still good
    voy2
    {Logs}
      09:00 Setting sail
      13:00 Iceberg, dead ahead
  002
  {Voyages}
    voy3
    {Logs}
      16:00 Ship 002 is lost

Это довольно хорошо, потому что позволяет делать вещи вроде этого:

// get all the voyages for ship 001
db.doc('Ships/001');

// get info and logs for voyage 1
db.doc('Ships/001/Voyage/voy1');

// get all the Logs across all voyages
collectionGroup('Logs');

И все другие приятные вещи, которые мы можемделать с вложенными коллекциями ...

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

Однако , мой вопрос: что произойдет, если мы обнаружим, что отношения в нашей схеме неверны?Например, мы находим, что журналы не обязательно связаны с рейсом, потому что корабли будут даже брать журналы, когда не в рейсе?Или что корабли могут быть сгруппированы в флоты - уровень выше кораблей.Должны ли мы перенести нашу схему?Нужно ли гибридизировать наши отношения, объединяя клиентский код и полагаясь на вложенную структуру?

1 Ответ

1 голос
/ 10 мая 2019

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

Fleets
  fleet0: {}

Ships
  ship0: { fleet: ref-to-a-fleet } // problem 2. no migration,
                                   // just add a fleet "foreign key"
  ...

Voyages
  voyage0: { ship: ref-to-a-ship }
  ...

Logs
  log0: { voyage: ref-to-a-voyage }
  log1: { ship: ref-to-a-ship }      // problem 1. "foreign key" can be to any
                                     // other collection

Это немного меняет ваш шаблон запроса, но надёжно.Приятной особенностью вашей текущей настройки является то, что коллекцию можно описать путем, но (поскольку firestore предоставляет индексы) это немного менее красиво, но примерно настолько же эффективно, как это сделать ...

// original design
db.doc('Ships/001');

// new design
let ship = db.doc('Ships/001');
db.collection('voyages').where('ship', '==', ship);

Затем обе ссылки могут быть отправлены get() для получения одного и того же querySnapshot.

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

Вот видео, в котором обсуждаются плюсы / минусы .Я бы охарактеризовал вывод как неоднозначный.Он указывает:

  1. как и я, что квалифицированный запрос на верхнем уровне (where id ==) примерно так же быстр, как и запрос во всей вложенной коллекции
  2. , чтоОрганизация верхнего уровня позволяет запрашивать вещи, охватывающие несколько родителей (это может быть очень важно для вас: что, если вы хотите, чтобы все рейсы совершались в определенный порт, независимо от корабля?).
  3. в другомhand: по моему предложению, если вы хотите отсортировать результаты по какому-либо запросу, вам придется создать составной индекс (простой, но дополнительный шаг разработчика).
  4. также, с другой стороны, это может бытьсложнее писать правила безопасности для коллекций верхнего уровня, например, когда правило зависит от данных в родительском (хотя get s также возможно в правилах безопасности)

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

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