Как реализовать систему тега

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

P.S. Отправленный Woodgnome при ожидании приглашают для присоединения

84
задан Chris 2 August 2012 в 08:20
поделиться

5 ответов

Думаю, вам будет интересно это сообщение в блоге: Теги: Схемы базы данных

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

Решение «MySQLicious»

В этом решении в схеме есть только одна таблица, она денормализована. Этот тип называется «решением MySQLicious», потому что MySQLicious импортирует данные del.icio.us в таблицу с этой структурой.

enter image description hereenter image description here

Пересечение (И) Запрос для «search + webservice + semweb»:

SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags LIKE "%semweb%"

Union (OR) Запрос на «поиск | веб-сервис | semweb»:

SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%"

Минус Запрос для «search + webservice-semweb»

SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%"

Решение «Scuttle»

Scuttle организует свои данные в двух таблицах. Эта таблица scCategories является таблицей «тегов» и имеет внешний ключ к таблице «закладок».

enter image description here

Пересечение (И) Запрос «закладка + веб-сервис + semweb»:

SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId
HAVING COUNT( b.bId )=3

Сначала ищутся все комбинации закладка-тег, где тег - «закладка», «веб-сервис» или «семвеб» (c.category IN ('закладка', 'веб-сервис ',' semweb ')), то учитываются только закладки, в которых был произведен поиск всех трех тегов (HAVING COUNT (b.bId) = 3).

Union (OR) Запрос для «закладка | веб-сервис | semweb»: Просто опустите предложение HAVING, и у вас будет объединение:

SELECT b.*
FROM scBookmarks b, scCategories c
WHERE c.bId = b.bId
AND (c.category IN ('bookmark', 'webservice', 'semweb'))
GROUP BY b.bId

Минус (Исключение) Запрос на «закладка + веб-сервис-semweb», то есть: закладка И веб-сервис, а НЕ semweb.

SELECT b. *
FROM scBookmarks b, scCategories c
WHERE b.bId = c.bId
AND (c.category IN ('bookmark', 'webservice'))
AND b.bId NOT
IN (SELECT b.bId FROM scBookmarks b, scCategories c WHERE b.bId = c.bId AND c.category = 'semweb')
GROUP BY b.bId
HAVING COUNT( b.bId ) =2

Если не указывать ИМЕЮЩИЙ СЧЕТ, появится запрос «закладка | веб-сервис-semweb».


Решение «Toxi»

Toxi придумал структуру из трех таблиц. В таблице «tagmap» закладки и теги связаны n-к-m. Каждый тег можно использовать вместе с разными закладками и наоборот. Эта схема БД также используется wordpress. Запросы такие же, как и в случае решения «спрятать».

enter image description here

Пересечение (И) Запрос для «закладка + веб-сервис + semweb»

SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id
HAVING COUNT( b.id )=3

Union (OR) Запрос «закладка | веб-сервис | semweb»

SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id

Минус (Исключение) Запрос «закладка + веб-сервис-semweb», то есть: закладка И веб-сервис, А НЕ semweb.

SELECT b. *
FROM bookmark b, tagmap bt, tag t
WHERE b.id = bt.bookmark_id
AND bt.tag_id = t.tag_id
AND (t.name IN ('Programming', 'Algorithms'))
AND b.id NOT IN (SELECT b.id FROM bookmark b, tagmap bt, tag t WHERE b.id = bt.bookmark_id AND bt.tag_id = t.tag_id AND t.name = 'Python')
GROUP BY b.id
HAVING COUNT( b.id ) =2

Отсутствие ИМЕЮЩЕГО СЧЕТА приводит к запросу «закладка | веб-сервис-semweb».

114
ответ дан 24 November 2019 в 08:36
поделиться

Нет ничего плохого в вашем решении с тремя таблицами.

Другой вариант - ограничить количество тегов, которые могут быть применены к статье (например, 5 в SO), и добавить их непосредственно в свой article table.

Нормализация БД имеет свои достоинства и недостатки, точно так же, как жесткое объединение вещей в одну таблицу имеет свои достоинства и недостатки.

Ничто не говорит о том, что нельзя делать и то, и другое. Повторение информации идет вразрез с парадигмами реляционных БД, но если целью является производительность, возможно, придется нарушить парадигмы.

8
ответ дан 24 November 2019 в 08:36
поделиться

Предлагаемое решение является лучшим - если не единственным практически осуществимым - способом, который я могу придумать для решения проблемы связи "многие ко многим" между тегами и статьи. Так что я голосую «да, он по-прежнему лучший». Хотя меня бы интересовали любые альтернативы.

3
ответ дан 24 November 2019 в 08:36
поделиться

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

2
ответ дан 24 November 2019 в 08:36
поделиться

Предложенная вами реализация трех таблиц будет работать для тегирования.

Однако переполнение стека использует другую реализацию. Они хранят теги в столбце varchar в таблице сообщений в виде обычного текста и используют полнотекстовую индексацию для извлечения сообщений, соответствующих тегам. Например, posts.tags = "передовой опыт системной маркировки алгоритмов" . Я уверен, что Джефф где-то упоминал об этом, но я забыл где.

Однако переполнение стека использует другую реализацию. Они хранят теги в столбце varchar в таблице сообщений в виде обычного текста и используют полнотекстовую индексацию для извлечения сообщений, соответствующих тегам. Например, posts.tags = "передовой опыт системной маркировки алгоритмов" . Я уверен, что Джефф где-то упоминал об этом, но я забыл где.

Однако переполнение стека использует другую реализацию. Они хранят теги в столбце varchar в таблице сообщений в виде обычного текста и используют полнотекстовую индексацию для извлечения сообщений, соответствующих тегам. Например, posts.tags = "передовой опыт системной маркировки алгоритмов" . Я уверен, что Джефф где-то упоминал об этом, но я забыл где.

6
ответ дан 24 November 2019 в 08:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: