Как внедрить систему многопользовательских тегов * голосования * (например, теги истории Slashdot) - PullRequest
0 голосов
/ 10 августа 2010

Этот вопрос несколько отличается от типичного вопроса «как создать систему тегов», который подробно обсуждался в SO и других местах.

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

Как система, как эта работает в целом? Например, Slashdot.org полагается на что-то подобное, чтобы придумывать теги истории. (никогда не редактируя теги, мне было бы интересно узнать больше о том, как это работает.)

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

doc:     id, name, ...
tag:     id, tag_name
doc_tag: doc_id, tag_id, user_id

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

SELECT
   doc_id, tag_id,
   num_times_tagged, taggers_count,
   num_times_tagged/taggers_count AS popularity

FROM doc_tag

LEFT JOIN (
   SELECT doc_id, tag_id, COUNT(*) AS num_times_tagged
   FROM doc_tag GROUP BY doc_id, tag_id
) num_times
ON doc_tag.doc_id = num_times.doc_id AND
   doc_tag.tag_id = num_times.tag_id

LEFT JOIN (
   SELECT doc_id, COUNT(DISTINCT user_id) AS taggers_count
   FROM doc_tag GROUP BY doc_id
) num_taggers
ON doc_tag.doc_id = num_taggers.doc_id

GROUP BY doc_tag.doc_id, doc_tag.tag_id

Я иду по этому поводу совершенно неправильно? Это кажется очень дорогим запросом. Предположим, я просто хотел получить список документов и главных тегов для каждого - как бы я написал для этого объединение? Я не хочу запускать этот запрос для каждого документа, который я получаю!

Спасибо за любой совет.

David

1 Ответ

0 голосов
/ 10 августа 2010

Вот более чистый запрос:

SELECT
   doc_id, 
   tag_id,
   COUNT(*) AS num_times_tagged, 
   COUNT(DISTINCT user_id) AS taggers_count,
   COUNT(*)/COUNT(DISTINCT user_id) AS popularity

FROM doc_tag
GROUP BY doc_tag.doc_id, doc_tag.tag_id

Кроме того, я не знаком со всеми RBDMS, но если вы используете Sql Server, вы можете создать представление, а затем кластерный индекс поверхвид.Это замедлит вставку до doctag, но сделает чтение из этого представления действительно быстрым.

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