Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > Мягкое удаление нунужных тегов


Автор: KonstRuctor 21.4.2009, 01:47
Работаю с администрированием статей и тегов к ним.
Есть три таблицы:
1) таблица статей articles
article_id | head | text | long_text
2) таблица тегов tags
tag_id | tag
3) таблица соответствий post_tags
id | tag_id | article_id
Удаляю статью под номеров $article_id из базы:
$result = $db->query("DELETE FROM articles WHERE article_id = '".$article_id."'");
Удаляю из таблицы соответствий
$result2 = $db->query("DELETE FROM post_tags WHERE article_id = '".$article_id."'");
В таблице tags остаются "сиротливые" теги, которые могут больше не понадобиться.
Но в то же время один из этих тегов может служить тегом к другой статье, его удалять нельзя.

Вопрос: оставить "сиротливые" теги болтаться, или как-то организовать их удаление?
Если удалять, то после $result2. Как составить такой запрос?

Автор: Kirsan 21.4.2009, 08:43
Если каждая запись в таблице tags сответствует только одной записи из articles, то поможет следующий запрос:
Код

mysql_query('DELETE FROM tags WHERE tag_id IN (SELECT tag_id  FROM post_tags WHERE article_id = \''.$article_id.'\');');

Его нужно выполнять ДО того, как очистите таблицу post_tags, т.е. до $result2.
Тогда из таблицы tags будут удалены только те теги, которые относятся к статье с article_id.

Если у Вас одна запись из таблицы tags может соответствовать нескольким записям из таблицы articles, то тогда всё несколько сложнее.

Автор: lelik133 21.4.2009, 08:47
вот пример из мануала http://dev.mysql.com/doc/refman/5.0/en/delete.html
Код

DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;

подставьте свои таблицу/столбцы

Автор: skyboy 21.4.2009, 13:49
Цитата(KonstRuctor @  21.4.2009,  00:47 Найти цитируемый пост)
оставить "сиротливые" теги болтаться, или как-то организовать их удаление?

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

Автор: KonstRuctor 22.4.2009, 00:08
lelik133, Спасибо, покопаюсь!!

skyboy, Я разрабатываю систему, скоро запущу. Хочу сделать по уму.

Kirsan, Вы пишите -- Если у Вас одна запись из таблицы tags может соответствовать нескольким записям из таблицы articles, то тогда всё несколько сложнее.
На самом деле, как видно из структуры таблиц, tags и articles никак не связаны. На то и создана таблица соответствий post_tags

Автор: Kirsan 22.4.2009, 01:23
Ну так та таблица и есть связь. При взаимоотношении "многое ко многому" такой вариант связи наиболее оптимален.
Приведу два примера:
1) К каждой новой статье теги задаются по новой. Тогда при создании каждой записи в articles у Вас в таблице tags будет создано n записей, привязанных к одной статье. При добавлении следующей статьи, существующие теги не проверяются. Поэтому может быть масса повторений в пределах таблицы tags. И в итоге каждый тег будет соответствовать только одной статье.
2) К каждой новой статье теги задаются на основе уже существующих, но с возможностью добавления новых. Тогда при создании новой записи в таблице articles, в таблице tags будут создаваться только те теги, которых ещё не было, т.е. повторы при нормальной реализации будут исключены. В этом случае у Вас один тег может использоваться в нескольких статьях.

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

//выбираем tag_id для удаляемой статьи
$result = mysql_query('SELECT tag_id FROM post_tags WHERE article_id='.$article_id.');');
$t = mysql_fetch_array($result);
$article_tags = implode(',',$t);
//ваш код по удалению статьи и соответствий
$result = $db->query("DELETE FROM articles WHERE article_id = '".$article_id."'");
$result2 = $db->query("DELETE FROM post_tags WHERE article_id = '".$article_id."'");
//теперь выбираем из таблицы post_tags только те tag_id, которые относились к удалённой статье, но остались в таблице соответствий (используются другими статьями)
$result = mysql_query('SELECT tag_id FROM post_tags WHERE tag_id IN ('.$article_tags.' ));');
$t = mysql_fetch_array($result);
$used_tags =  implode(',',$t);
//А теперь удаляем из таблицы tags те теги, которые использовались в удалённой статье, но при этом не используются в других
$result = mysql_query('DELETE FROM tags WHERE (tag_id IN ('.$article_tags.') AND tag_id NOT IN ('.$used_tags.'));');


Добавлено через 6 минут и 7 секунд
Хм. Почему-то подсветка не хочет работать. Код вроде корректный, у меня редактор нормально кусок подсвечивает.

Автор: KonstRuctor 22.4.2009, 16:23
УФФ!!!
Я не додумался до решения с помощью $article_tags = implode(',',$t);
Попробуем, попробуем!

Да, конечно, каждый раз при добавлении статьи добавляются теги. Автоподставы (словечко еще то smile пока нету.
Теоретически в таблице tags должны быть только уникальные теги. 
Однако Санкт-Петербург и санкт-петербург вроде как два разных тега. Согласен, что автозаполнение поможет решить эту проблему, так как юзер начнет заполнять "сан.." и тут ему — рраз и предложат как грамотно сделать.

Спасибо! Вечером буду копаться. О результатах сообщу

Автор: Kirsan 22.4.2009, 16:32
Ну теги при добавлении можно и через strtolower() прогонять. Или разбивать на первый символ и всё остальное, первый символ делать большим, а последующие маленькими. В общем сделать так, чтобы добавлялись теги всегда в одном регистре. Тогда часть повторов отпадёт. Главное с кодировками не напутать при преобразовании.

Автор: skyboy 22.4.2009, 20:05
Цитата(KonstRuctor @  22.4.2009,  15:23 Найти цитируемый пост)
Однако Санкт-Петербург и санкт-петербург

кривой рог и rhbdjq hju  - тоже разные теги, хотя это одно и то же в разных раскладках. и "среда" со "сридой" как бы означают единое.
если у тебя теги только для поиска то либо ручная модерация списка(возможно, используя расстояние Левенштейна или soundex для поиска кандидатов в дубликаты), либо  забить.
если у тебя теги и для SEO(meta name="keywords", например), то варианты с ошибками и не в той раскладке даже круче, чем только один "правильный" вариант.

Автор: KonstRuctor 22.4.2009, 23:34
Решение, которое описано в документации MySQL и которое мне предложил lelik133 оказалось очень изящным и красивым. И при этом компактным. Все работает! Теги-сироты удаляются! Отлично.
Буду знать эту технику. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)