ListProperty of keys vs Many-to-Many в App Engine

В качестве гипотетического примера у меня есть модель TodoItem и модель TodoList. У TodoList есть упорядоченный список TodoItems, и любой TodoItem может принадлежать любому числу TodoLists (Many-to-Many). Никакая другая информация не должна храниться в отношении их отношений, кроме порядка TodoItem в TodoList. Каков наилучший способ представить это в хранилище данных?

Существует два способа реализовать это: присвойте классу TodoList ListProperty из db.Key, который будет ссылаться на TodoItem's:

class TodoList(db.Model):
  items = db.ListProperty(db.Key)

или создать модель ListItem, которая также содержит информацию для заказа:

class TodoListItem(db.Model):
  item = db.ReferenceProperty(TodoItem)
  list = db.ReferenceProperty(TodoList)
  order = db.IntegerProperty()

Я определенно буду оптимизировать это позже путем денормализации моделей, но предварительная оптимизация, имеет ли какое-либо одно представление преимущество над другим?

Ответ 1

Это зависит от нескольких факторов:

  • Вам нужно хранить информацию о самом отношении, кроме его порядка? Например, многие: многие между заказами и продуктами должны хранить количество каждого продукта.
  • Вам нужно связать более тысячи элементов со стороны отношения с "меньшей" мощностью (например, > 1000 предметов todo или > 1000 списков для элемента)?
  • Обычно вы хотите получить все связанные элементы сразу или хотите быть более избирательными?

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

Ответ 2

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

Ответ 3

Учитывая, что TodoListItem может принадлежать нескольким TodoLists, я был бы обеспокоен тем, что было бы справедливо иметь одно свойство заказа, которое будет работать для каждого списка, к которому принадлежит элемент. Я бы подумал, что для элемента будет нужен Ордер для каждого списка, к которому он принадлежит.