Реалізація коментарів та сподобань у базі даних


146

Я розробник програмного забезпечення. Я люблю кодувати, але ненавиджу бази даних ... Зараз я створюю веб-сайт, на якому користувачеві буде дозволено позначати суб'єкт господарювання як сподобався (як у FB), позначити його та прокоментувати .

Я застрягаю в дизайні таблиць баз даних для обробки цієї функціональності. Рішення є тривіальним, якщо ми можемо це зробити лише для одного типу речей (наприклад, фотографій). Але мені потрібно ввімкнути це для 5 різних речей (наразі, але я також припускаю, що ця кількість може зростати, коли зростає вся служба).

Тут я знайшов кілька подібних запитань, але жодне з них не має задоволеної відповіді, тому я задаю це питання ще раз.

Питання полягає в тому, як правильно, ефективно та еластично спроектувати базу даних, щоб вона могла зберігати коментарі до різних таблиць , лайків для різних таблиць та тегів для них. Якась модель дизайну як відповідь буде найкращою;)

Детальний опис : у мене є таблиця User з деякими даними користувачів і ще 3 таблиці : Photoз фотографіями , Articlesзі статтями , Placesз місцями . Я хочу ввімкнути будь-якого зареєстрованого користувача:

  • прокоментуйте будь-яку з цих 3 таблиць

  • позначте будь-який із них як сподобався

  • позначте будь-який із них тегом

  • Я також хочу порахувати кількість лайків для кожного елемента та кількість разів, коли цей тег був використаний.

1- й підхід :

а) Для тегів , я створити таблицю Tag [TagId, tagName, tagCounter] , то я буду створювати багато-до-багатьох відносини таблиць для: Photo_has_tags, Place_has_tag, Article_has_tag.

б) Те саме вважається за коментарі.

в) я створю таблицю LikedPhotos [idUser, idPhoto] , LikedArticles[idUser, idArticle], LikedPlace [idUser, idPlace]. Кількість лайків буде розрахована за запитами (що, я вважаю, це погано). І ...

Мені дуже не подобається ця конструкція останньої частини, вона погано пахне для мене;)


2 - й підхід :

Я створити таблицю , ElementType [idType, TypeName == some table name]яка буде заповнюватися адміністратором (мене) з іменами таблиць , які можуть бути сподобалися , коментували або помічені . Тоді я буду створювати таблиці :

а) LikedElement [idLike, idUser, idElementType, idLikedElement]те саме для коментарів і тегів із відповідними стовпцями для кожного. Тепер, коли я хочу зробити сподобалось фото, я вставив:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)

і для місць:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)

і так далі ... Я думаю, що другий підхід кращий, але я також відчуваю, що щось не вистачає і в цій конструкції ...

Нарешті, мені також цікаво, яке найкраще місце для зберігання лічильника, скільки разів сподобався елемент. Я можу думати лише про два способи:

  1. в Photo/Article/Placeтаблиці елементів ( )
  2. шляхом вибору count ().

Я сподіваюся, що моє пояснення цього питання більш ґрунтовне.


Ви розглядали XML?
CodyBugstein

1
Я рідко знаходжу подібні запитання, які на 100% є моїми думками, ваше питання надзвичайно повне! Дякую @Kokos.
aderchox

Відповіді:


195

Найбільш розширене рішення - мати лише одну "базову" таблицю (підключену до "лайків", тегів та коментарів) та "успадкувати" всі інші таблиці з неї. Додавання нового типу сутності означає просто додавання нової "успадкованої" таблиці - вона автоматично підключається до цілої машини, як / тег / коментар.

Термін відносин між особами для цього є "категорією" (див. Посібник з методів ERwin , розділ: "Взаємовідносини підтипу"). Символ категорії:

Категорія

Якщо припустити, що користувачеві можуть подобатися декілька сутностей, один і той же тег може використовуватися для більш ніж однієї сутності, але коментар залежить від сутності, ваша модель може виглядати так:

Діаграма ЕР


До речі, існує приблизно 3 способи реалізації "категорії ER":

  • Усі типи в одній таблиці.
  • Всі типи бетону в окремих таблицях.
  • Усі конкретні та абстрактні типи в окремих таблицях.

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


2
чудова відповідь, дякую. Я сподіваюсь, мені вдасться його реалізувати ... і мені цікаво, як Django ORM впорається з картою (або як я це зроблю сам ... але це інша проблема;)) Але, чи можете ви пояснити мені, тому що я думаю, що я не розумію це належним чином - те, що ви намалювали для мене (спасибі!) - третій підхід, про який ви згадали?
Кокос

2
@Kokos По суті, підхід (3) означає, що ENTITY - це таблиця, PHOTO - це таблиця, ARTICLE - це таблиця, а PLACE - це таблиця. Підхід (2) означатиме, що немає таблиці ENTITY, а підхід (1) означатиме, що існує лише одна таблиця. Наявність усіх цих підходів (усі з їх сильних і слабких сторін) є невдалим наслідком того факту, що типова RDBMS не підтримує спадкове використання таблиці.
Бранко Димитріевич

1
+1 спасибі за чудове пояснення та посилання на "категорії". Я збирався розмістити питання, близьке до цього, але ви тут відповіли.
Енді Холадей

2
@BrankoDimitrijevic Чому не можуть таблиці таблиць сутності Фото, Стаття, Місце мати власну ПК, наприклад, PhotoID, ArticleID тощо, але також мають ще один стовпець для Entity_ID як FK? Це зайве?
том 1

3
@Orion Максимум для BIGINT- 9223372036854775807. Якщо припустити, що ви вставляєте один рядок щосекунди, ви втратите доступні значення за ~ 300 мільярдів років. Звичайно, ви зможете до того часу перенести 128-бітні цілі числа!
Бранко Димитріевич

22

Оскільки ви «ненавидите» бази даних, чому ви намагаєтесь їх впровадити? Натомість вимагайте допомоги у того, хто любить та дихає цим матеріалом.

Інакше навчіться любити свою базу даних. Добре розроблена база даних спрощує програмування, інженерію сайту та згладжує його подальшу роботу. Навіть досвідчений дизайнер не може мати повний і ідеальний прогноз: потрібні деякі зміни схеми вниз по дорозі, коли з'являться шаблони використання або змінюються вимоги.

Якщо це індивідуальний проект, запрограмуйте інтерфейс бази даних на прості операції, використовуючи збережені процедури: add_user, update_user, add_comment, add_like, upload_photo, list_comments тощо. Не вкладайте схему в один рядок коду. Таким чином, схему бази даних можна змінити, не впливаючи на будь-який код: про схему повинні знати лише збережені процедури.

Можливо, вам доведеться кілька разів переробляти схему. Це нормально. Не хвилюйтеся про те, що ви вдосконалите його в перший раз. Просто зробіть його досить функціональним для прототипу початкового дизайну. Якщо у вас є розкіш часу, скористайтеся ним, а потім видаліть схему і повторіть це. Це завжди краще вдруге.


2
Тому що мені потрібно це реалізувати самостійно. Принаймні поки що ... і я подумав, що, можливо, це хороший привід почати трохи сподобатися базам даних;) Дякую за вашу пропозицію із збереженою процедурою. Хтось знає, якщо вони автоматично відображаються Django ORM?
Кокос

6
Я люблю твоє останнє речення - Це завжди краще другий раз.
Льюїс

2
Завжди краще другий раз. Yup
Гаммер

20

Це загальна ідея, будь ласка, не приділяйте багато уваги стилям назв полів, а більше відношенню та структурі

введіть тут опис зображення

Цей псевдокод отримає всі коментарі до фотографії з ідентифікатором 5
ВИБІР * ВІД дій,
де ДЕРЖАВИ.id_Stuff = 5
AND Actions.typeStuff = "фото"
І actions.typeAction = «коментар»

Цей псевдокод отримає всіх лайків або користувачів, які сподобалися фото з ідентифікатором 5
(ви можете використовувати count (), щоб отримати лише кількість лайків)

SELECT * FROM actions  
WHERE actions.id_Stuff = 5  
AND actions.typeStuff="photo"  
AND actions.typeAction = "like"  

Я думаю, що вам можуть навіть сподобатися коментарі, як, натискаючи посилання "як" у коментарі. Цей запит отримає SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
сподобання

1
Я обов'язково запам’ятаю це рішення для подальших випусків моєї системи :)
Kokos

У мене є 2 таблиці матеріалів stuff1 і stuff2 ... Я дотримувався цієї діаграми, але є помилка sql під час використання цього ... stuff1, stuff2 - це дві незалежні таблиці зі своїми незалежними первинними ключами, а таблиця дій має стовпець id_stuff, який посилається на ці два вкладки stuff1, stuff2. Тепер, наприклад, у stuff1 є 5 рядків, у stuff2 є 10 рядків, коли я намагаюся додати рядок у таблицю дій з id_stuff чим-небудь меншим, ніж 5 дозволяє сказати "3", він виконує запит, тому що існує рядок з id_stuff '3' в обох stuff1 та stuff2, але якщо я спробую додати рядок з id_stuff більше 5 ... (продовжити до наступного коментаря)
vikas devde

1
Якщо реалізувати лайки таким чином, це ускладнить сповіщення користувача про нові лайки. Для цього знадобиться інша таблиця.
Грег Л

4
Як id_stuffстовпець буде містити унікальні значення в кожній з трьох таблиць?
том перший

0

наскільки я розумію. потрібно кілька таблиць. Між ними існує багато відношень.

  • Таблиця, в якій зберігаються дані користувача, такі як ім’я, прізвище, дата народження з полем ідентичності.
  • Таблиця, в якій зберігаються типи даних. ці типи можуть бути фотографіями, поділками, посиланнями. кожен тип повинен мати унікальну таблицю. тому існує взаємозв'язок між їх окремими таблицями та цією таблицею.
  • кожен тип даних має свою таблицю. наприклад, оновлення статусу, фотографії, посилання.
  • остання таблиця для багатьох-багатьох стосунків зберігає ідентифікатор, ідентифікатор користувача, тип даних та ідентифікатор даних.

якщо ви розмістите свою схему бази даних. я можу зробити відношення.
erencan

0

Подивіться на схеми доступу, які вам знадобляться. Чи здається, що будь-який із них зробив особливо складним чи неефективним моє вибір одного дизайну чи іншого?

Якщо не користь тієї, яка потребує меншої кількості таблиць

В цьому випадку:

  1. Додати коментар: ви або вибираєте певну таблицю багато / багато, або вставляєте в загальну таблицю з відомим конкретним ідентифікатором для того, що вам подобається, я думаю, що клієнтський код буде трохи простішим у вашому другому випадку.
  2. Знайти коментарі до елемента: тут, здається, використовувати загальну таблицю трохи простіше - у нас є лише один запит, параметризований за типом сутності
  3. Знайдіть коментарі людини щодо одного виду: простий запит в будь-якому випадку
  4. Знайдіть усі коментарі людини щодо всіх речей: це так чи інакше здається.

Я думаю, що ваш "дискримінаційний" підхід, варіант 2, дає простіші запити в деяких випадках, а в інших не здається набагато гіршим, тому я б пішов з ним.


0

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


-1

Розгляньте можливість використання таблиці за суттю для коментарів тощо. Більше таблиць - краща різкість та масштабування. Це не проблема контролювати багато подібних таблиць для всіх моїх фреймів.

Одного разу вам потрібно буде оптимізувати читання з такої структури. Ви можете легко створити аграгуючі таблиці над базовими та трохи втратити на записі.

Одна велика таблиця зі словником може стати некерованою за один день.


Більше таблиць означає, що це буде менш рентабельним. Окремі таблиці можуть бути розбиті більшістю d / bs.
wallyk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.