Разработка схемы базы данных для сравнения продуктов - PullRequest
0 голосов
/ 30 апреля 2019

Я хочу разработать схему базы данных для сравнения двух продуктов.Примерно так: https://www.capterra.com/agile-project-management-tools-software/compare/160498-147657/Clubhouse-vs-monday-com

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

  1. Таблица категорий, помечающая категорию продукта.
  2. Сохраняет все функции, соответствующие категории, в таблице категорий.
  3. В таблице продукта хранится массив для каждой функции, где ключом является функция.name, value - это значение этой функции в продукте, а category_feature_id - это feature_id в таблице категорий.

Однако это делает таблицу продуктов очень тесно связанной с таблицей категорий.Кто-нибудь работал над такой проблемой раньше?Любые указатели будут оценены.Вот краткий обзор схемы:

categories collection:

name: 'String'
features: [
{
name: 'string'
parent_id: 'ObjectID' // if this is a sub feature it will reference in this // embedded document itself
}
]

products:
name: 'String'
features: [ // Embedded document with feature values
{
name: 'String',
value: Boolean,
category_feature_id: 'ObjectID' // feature_id into the categories.features // table, majorly used to comparison only.
}
]

1 Ответ

1 голос
/ 30 апреля 2019

Я бы подумал о том, чтобы сделать функции отдельной коллекцией, и для каждой категории или продукта есть список идентификаторов функций.Так, например:

Features collection:
{id: XXX, name: A}, {id: YYY, name: B}

Categories collection:
{ features: [featureId: XXX, value: C]}

Products collection:
{ features: [featureId: YYY, value: D]}

Это имеет несколько преимуществ:

  1. Концептуально, я бы сказал, что функции не зависят от категорий и продуктов.Если вы не уверены, что две категории никогда не будут совместно использовать функцию, у вас не должно быть повторяющихся определений одной функции.В противном случае, если вы когда-нибудь захотите обновить функцию позже (например, ее имя или другие атрибуты), это будет затруднительно.
  2. Это облегчает привязку функций к продуктам и / или категориям безтак тесно связана с определениями в каждой категории.
  3. Это позволяет существенно переопределить элементы категории в продукте, если вы хотите, путем включения одной и той же функции в категорию и конкретный продукт.Вы можете решить, что эта ситуация значит для вас.Но один из способов определения этого условия состоит в том, что определение продукта функции заменяет определение категории, создавая очень гибкую схему.
  4. Это позволяет пользователям искать отдельные функции по категориям и продуктам.Например, в будущем вы можете разрешить пользователям выполнять поиск определенного цвета по нескольким категориям и продуктам.Рассматривая объекты как объекты 1-го класса, вы сможете сделать это без необходимости обходить их, переводя пользовательский запрос в несколько category_feature_id.
  5. Вам не нужно поле category_feature_id, потому что у каждой функции одинаковый идентификатор во всех продуктах.и категории, так что легко сделать ссылку на товар и категорию.

В любом случае, это моя рекомендация.И если вы добавите индекс к массиву функций в коллекциях категорий и продуктов, то выполнение операций с БД, таких как поиск, объединение, фильтры и т. Д., Будет очень быстрым.

РЕДАКТИРОВАТЬВаш комментарий):

Решение о денормализации имени объекта является ортогональным к решению о том, где хранить запись объекта.Позвольте мне перевести это: -)

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

Согласно теории отношений вы хотитемаксимально нормализовать данные, потому что это самый простой способ поддержания согласованности.Например, если у вас есть только одно место для записи адреса клиента, вы никогда не окажетесь в ситуации, когда у вас есть два адреса, и вы не знаете, какой из них правильный.Однако люди часто нормализуют данные по причинам производительности, а именно, чтобы избежать дорогостоящих и / или частых запросов.Решение об отмене нормализации данных должно сопоставлять преимущества в производительности с затратами на поддержание согласованности данных вручную (теперь вы должны написать код приложения, чтобы гарантировать, что различные копии данных остаются согласованными при обновлении любой из них).

Это то, что я подразумеваю под денормализацией, ортогональной к структуре данных: вы выбираете структуру данных, которая наиболее целесообразна для точного представления ваших данных.Затем вы выборочно отменяете нормализацию по причинам производительности.Конечно, вы не выбираете окончательную структуру данных без учета влияния на производительность, но концептуально это две разные цели.Имеет ли это смысл?

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

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

OTOH, если вы не продумали преимущества производительности и просто придерживаетесь этой парадигмы, потому что "noSQL не выполняет объединений", тогда я рекомендую не быть таким догматичным! :-) Вы можете делать соединения в MongoDB довольно быстро, так же как вы можете легко денормализовать данные в таблицах SQL. Это не сложные и быстрые правила.

FWIW, ИМХО, я думаю, что нормализация во избежание простого запроса - это случай преждевременной оптимизации. Если у вас нет веб-сайта, который обслуживает> 10 тыс. Страниц продукта в секунду вместе с> 1 тыс. Вставок или обновлений в секунду, что приводит к значительным задержкам блокировки, дополнительный запрос на чтение в коллекцию функций (особенно если вы правильно проиндексированы) добавит очень минимальные издержки. И даже в этих сценариях вы можете много оптимизировать запросы, прежде чем начинать денормализацию (например, на странице категории, показывающей несколько продуктов, вы можете выполнить один пакетный запрос, чтобы получить все записи объектов в одном запросе).

Примечание: есть один способ избежать и того, и другого - сделать имя каждой функции уникальным, а затем использовать , в качестве ключа. То есть не храните featureId, просто сохраните имя объекта и выполните запрос на основе этого, если вам нужны дополнительные данные из коллекции объектов. Однако я настоятельно рекомендую против этого. Единственное, в чем я догматичен, так это в том, что первичный ключ никогда не должен содержать никакой полезной информации. Вы можете подумать, что сейчас это умно, но через год вы будете ругаться за свое решение (например, что произойдет, когда вы решите интернационализировать сайт, и у каждой функции будет несколько имен? Что, если вы хотите иметь более обширные фильтры, где каждая функция имеет несколько синонимов, многие из которых пересекаются?). Поэтому я не рекомендую этот маршрут. Лично я предпочел бы взять на себя минимальные дополнительные накладные расходы на запрос.

...