2010-04-08 5 views
8

J'ai des articles sur mon site, et je voudrais ajouter des balises qui décriraient chaque article, mais j'ai des problèmes avec la conception de table mysql pour les balises. J'ai deux idées:Comment concevoir une table MySql pour un nuage de tags?

  1. chaque article aurait champ "balises", et les balises seraient en format: "balise1, tag2, tag3"
  2. créer d'autres balises appelé table avec des champs: tag_name, article_ID

alors, quand je veux des tags pour l'article avec ID 1, je courrais

SELECT ... FROM tags WHERE `article_id`=1; 

Mais, je voudrais aussi savoir 3 articles les plus semblables en comparant les étiquettes, donc si je l'article qui a des balises " php, mon sql, erlang ", et 5 articles avec des balises:" php, mysql "," erlang, ruby ​​"," php erlang "," mysql, erlang, javascript ", je choisirais 1., 3. et 4., puisque ceux 3 ont la plupart des mêmes tags avec l'article principal.

Également une autre question, quelle est la meilleure façon d'obtenir 10 "tags les plus utilisés"?

Répondre

18

En général, pour ce genre de plusieurs à plusieurs, il y a trois tables:

  • Le "article" Table
    • clé primaire = id
  • Le " tag "table
    • clé primaire = id
    • contient les données de chaque tag:
        nom
      • , par exemple
  • A "tags_articles" table, qui agit comme une table de jointure, et ne contient que:
    • id_article: clé étrangère pointant vers un article
    • id_tag: clé étrangère pointant vers une étiquette


De cette façon, il n'y a pas duplication de données de toute étiquette: pour chaque balise, il y a une, et une seule ligne dans le tableau tag. Et, pour chaque article, vous pouvez avoir plusieurs étiquettes (c'est-à-dire plusieurs lignes dans le tableau tags_articles); et, bien sûr, pour chaque tag, vous pouvez avoir plusieurs articles.

Obtenir une liste des tags pour un article, avec cette idée, est une question d'une requête additionnelle, comme:

select tag.* 
from tag 
    inner join tags_articles on tag.id = tags_articles.id_tag 
where tags_articles.id_article = 123 


Obtenir les trois articles « plus similaires » signifierait:

  • articles sélectionnés qui ont des étiquettes que le premier article a
  • utiliser uniquement ceux qui ont le nombre le plus important de balises identiques

Non testé, mais une idée peut-être quelque chose qui ressemblerait à ceci:

select article.id, count(*) as nb_identical_tags 
from article 
    inner join tags_articles on tags_articles.id_article = article.id 
    inner join tag on tag.id = tags_articles.id_tag 
where tag.name in ('php', 'mysql', 'erlang') 
     and article.id <> 123 
group by article.id 
order by count(*) desc 
limit 3 

Fondamentalement, vous:

  • sélectionner les articles ids pour chaque balise qui est présente sur votre premier article
    • comme il y a une jointure interne, si un article dans la base de données possède 2 balises qui correspondent à la clause where, sans la group by cl ause, il y aurait deux lignes pour cet article
    • bien sûr, vous ne voulez pas re-sélectionner l'article que vous aviez déjà - ce qui signifie qu'il doit être exclu.
  • mais, comme vous utilisez group by article.id, il n'y aura qu'une seule ligne par article
    • mais vous serez en mesure d'utiliser count, pour savoir combien de balises chaque article a en commun avec la première un
  • ensuite, il s'agit seulement de trier par nombre de balises, et d'obtenir seulement les trois troisièmes lignes.
+0

oui, mais vous n'avez pas répondu à ma question principale, comment obtenir 3 articles les plus similaires? – mfolnovich

+1

@mfolnovich: J'ai édité ma réponse plusieurs fois, pour ajouter plus d'informations sur le design; et, ensuite, en voyant votre commentaire, j'ai réédité, pour ajouter une idée possible de solution pour obtenir les 3 articles les plus similaires. –

1

Tout d'abord, vous voudrez utiliser la suggestion de Pascal MARTIN sur la conception de la table. Comme pour trouver des articles similaires, voici quelque chose pour vous aider à démarrer. Étant donné que @article_id est l'article que vous souhaitez trouver des correspondances pour et @ balise1, @ tag2, @ tag3 sont les balises pour cet article:

SELECT article_id, count(*) 
FROM tags_articles 
WHERE article_id <> @article_id 
AND tag_id IN (@tag1, @tag2, @tag3) 
GROUP BY article_id 
ORDER BY count(*) DESC 
LIMIT 3 
0

oui, mais vous ne l'avez pas répondu à ma question principale, comment obtenir 3 articles les plus similaires?

Réponse: Recherchez simplement les mêmes ID de balise dans la table fusionnée (tags_articles). Rassemblez-les et créez un motif.

Par exemple: Article 1 a tags: 1,2 Article 2 a tags: 2,3,4 Article 5 a tags: 6,7,2 article 7 a tags: 7,1,2, 3

Si vous voulez les 3 articles les plus similaires pour l'article 1, vous devez rechercher les étiquettes 1,2. Vous trouverez l'article 7 est le plus similaire et 2 et 5 ont quelques similitudes.

Questions connexes