Реализация многие-ко-многим с одним «основным» значением - PullRequest
2 голосов
/ 21 апреля 2011

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

products: id, ...
products_categories: product_id, category_id
categories: id, ...

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

  1. Добавить столбец is_primary к products_categories OR

  2. Добавить столбец primary_category_id к products

Каков наилучший способ реализовать это в чистом SQL и / или ActiveRecord? Я использую PostgreSQL, для чего он стоит.

Ответы [ 4 ]

1 голос
/ 21 апреля 2011

Я бы выбрал вариант (1).Причина этого заключается в том, что поскольку ваши продукты могут принадлежать более чем к одной категории, атрибут отношения (то есть его «первичная» категория) относится к таблице, которая определяет отношение.что вместо того, чтобы маркировать поле 'is_primary', у вас должно быть поле, помеченное как 'association_type'.И вместо того, чтобы просто добавить битовое поле, сделайте его целочисленным полем и определите все типы ассоциаций.В вашем случае сегодня есть только два типа ассоциации - вторичная и первичная.Преимущество в том, что этот дизайн гораздо более масштабируемый.Если завтра вас попросят определить «первичную», «вторичную» и все другие третичные категории, эта схема сможет обработать ее, вместо того, чтобы добавлять другое поле для обозначения «вторичного» поля.

1 голос
/ 21 апреля 2011

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

Если у вас есть primary_category_id:

  • Кажется, чище иметь одно поле вproduct говорит, что category является основным, чем иметь поле в каждом product_category, в котором 1 в одной строке и 0 в каждой другой строке, хотя MR рекомендует использовать association_type тоже звучит чисто - но какова вероятность того, что у вас будут «третичные» категории?
  • Немного легче попасть в основную категорию
  • Легко убедиться, что у каждого продукта всегда естьосновная категория (просто укажите поле NOT NULL)
  • . Это автоматически приводит к тому, что продукт может иметь только одну основную категорию
  • . Следует ли также добавить основную категорию в products_categories?
    • Ни одна из этих опций не применяется.
    • Если вы этого не сделаете, запросить все категории будет неудобно
    • Если вы это сделаете, запрос по-прежнему будет простым, но без дополнительной работы, ничто не гарантирует, что основная категория также будет вставлена ​​в другую таблицу

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

1 голос
/ 21 апреля 2011

Я бы выбрал первый вариант, если у меня нет веских причин для выбора 2 (например, стоимость дополнительного объединения при получении основной категории)

причина: вам, вероятно, нужно добавить основную категорию вВ любом случае таблица product_category (чтобы использовать ее единообразно и просто в запросах, таких как получение всех категорий для продукта), опция 1 позволяет избежать дублирования основной категории, что упрощает

0 голосов
/ 21 апреля 2011

Каковы плюсы и минусы каждого способа?

Вариант 1. Я могу быть уверен, что основная категория для продукта действительно является одной из его категорий.Но может возникнуть проблема с обеспечением того, чтобы продукт имел не более одной основной категории.

Вариант 2. Это позволяет мне убедиться, что продукт имеет только одну основную категорию.Но тогда у меня, похоже, нет способа убедиться, что это одна из категорий этого же продукта.

Так что, я бы, наверное, выбрал третий вариант , используя таблицу Products_PrimaryCategories:

Products_PrimaryCategories: product_id, category_id

Похоже на product_categories, но имеет некоторые дополнительные свойства:

  • product_id имеет связанный уникальный индекс, убедившись, чтоВы можете иметь только одну основную категорию для каждого продукта;

  • (product_id, category_id) - это внешний ключ, ссылающийся на products_categories (product_id, category_id), гарантирующий, что основная категория продукта относится к его категории (что означает, что (product_id, category_id) должен быть первичным ключом products_categories).

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