Ломаю голову как лучше спроектировать БД для разных типов предметов. Вот что дано:
1) Есть несколько типов предметов, большинство параметров одинаковы, различаются 2-5 характеристиками
2) Больше типов появляться не будут, возможно, но с минимальным процентом, появляться еще 2-3 параметра (не скоро, но нужно учесть)
Вообщем нужен оптимальный вариант таблиц.
Вот два варианта, которые кажутся оптимальными:
1) Разные таблицы
— Собрать все единые характеристики в одной таблице;
— Остальные характеристики разбить по разным таблицам, где таблица отвечает за свой «тип» предмета, с его характеритиками.
Нравиться: это более менее «правильно»
Не нравиться: на довольно простой системе это порождает излишнюю сложность, так как всегда нужно отслеживать, где что выбирать.
2) Собрать все в одной таблице.
— все в одной таблице, при всех возможных вариантов получилось 22 колонки;
Нравиться: все прозрачно, при минимальном проценте расширения проблем не предвидится, простые запросы при создании фильтров и все подобное.
Не нравиться: «не правильно»
Кто-нить может посоветоваться, может не все подводные камни вижу? Идеи, как реализовать лучше, в данном контексте?
EAV — отпадает сразу, так как все известно заранее и городить «подовсе» на мой взгляд глупо
NoSQL — нра, но не позволяют
3) Сделать отдельную таблицу под каждый предмет.
Это единственно правильный вариант. С первым вариантом Вы будете всегда лишний запрос делать к той «общей» таблице. Да и всё общее всегда будет конфликтовать. Захотите вы переименовать свойство — а нельзя, потому что остальные предметы его тоже юзают. Добавите свойство с префиксом и постепенно вырастет фигня. Второй вариант вообще ппц :)
OnYourLips, как же он его нарушает то? Бред какой-то. То, что свойства их совпали в определённый момент — чистое совпадение, не более того. Они должны быть изолированы.
SilentSokolov, делайте, кто мешает то? ORM? Что за ORM такая? Нормальную ORM возьмите. DataMapper используйте, если ORM такая хрупенькая.
OnYourLips, последнее предложение прочитайте в статье про ClassTable.
Проблема не в рефакторинге, а в том, что другие объекты ожидают старого имени для свойства.
По Вашей забавной логике, все поля id в таблицах надо вынести в одно, ибо копипаста :) Только DRY совсем не об одинаковых строках текста, а об одинаковой логике.
OnYourLips, это-то понятно, не понятно какой лучше при будущих «выборках», при том что ОРМ не держит DataMapper, другие полезные фишки, а проект мне еще поддерживать и писать черта-срогами не хочется.
делайте, кто мешает то? ORM? Что за ORM такая? Нормальную ORM возьмите. DataMapper используйте, если ORM такая хрупенькая.
Во-первых, это не совпадение, и именно отношение «это есть». Даже с ORM бывает не все так просто, а автор вопроса пишет еще и про фильтры. К сожалению вопрос действильно сложный и насущный. SilentSokolov, Я так понимаю, что проект (или эта часть проекта) довольно молодая, подумайте при каком подходе будет проще сменить его на другой подход. Т.е. выберете тот, при переходе с которого на другой не надо будет ломать голову и городить стоэтажные запросы.
1 — виртуальная молекула, 2 — динозавр.
То, что у них есть одинаковые по названиям свойства — совпадение, оно не даёт никакого повода выносить их в отдельную таблицу.
Принцип единой ответственности всегда главнее всех остальных. Иллюзорное удобство «одинаковое объединить» выльется в проблемы, особенно с течением времени.
EugeneOZ, думаю стоит уточнить, что мы будет хранить только виртуальные молекулы, просто разных типов. Когда начнем хранить и динозавров возможно перейдем на NoSQL :), но не скоро.
Document {id, name, ...}
Tag {id, type, createdAt, origin, duplicate, editable, removedAt}
DocumentTag {documentId, tagId}
Company {id, tagId, name, display name, url, ... еще пять параметров}
Location {id, tagId, lat, lon, country, state, city, ...}
и еще пять шесть тегов
?
Все сложить в одну таблицу — слишком жирно. С Single TI — стоэтажные запросы, при добавлении еще одного параметра или тега надо обойти кучу мест и поправить код.
4. Вынести параметры в отдельную таблицу параметров.
Все что общее пусть будет в одной таблице, как в первом варианте. А будет еще вторая таблица, содержащая id предмета, идентификатор параметра и соответственно значение параметра.
Выбрать все параметры очень просто по id.
При поиске немного сложнее, но достаточно выбрать все пары идентификатора параметра и его значение. Ну соответственно ищем те предметы у которых совпало число искомых и найденных пар.