2010-04-08 24 views
8

Tengo artículos en mi sitio, y me gustaría agregar etiquetas que describan cada artículo, pero estoy teniendo problemas con la tabla mysql de diseño para las etiquetas. Tengo dos ideas:¿Cómo diseñar una tabla MySql para una nube de etiquetas?

  1. cada artículo habría de campo "etiquetas", y las etiquetas sería en el formato: "etiqueta 1, etiqueta 2, etiqueta 3"
  2. crear otras etiquetas de tabla llamada con campos: tag_name, article_id

así que cuando quiero etiquetas de artículo con ID 1, yo correría

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

Pero, también me gustaría saber 3 artículos más similares mediante la comparación de las etiquetas, por lo que si tengo artículo que tiene las etiquetas " php, mi sql, erlang ", y 5 artículos con etiquetas:" php, mysql "," erlang, ruby ​​"," php erlang "," mysql, erlang, javascript ", elegiría 1., 3. y 4., ya que esos 3 tienen la mayoría de las mismas etiquetas con el artículo principal.

También otra pregunta, ¿cuál es la mejor manera de obtener 10 "etiquetas más usadas"?

Respuesta

18

En general, para este tipo de muchos-a-muchos relación, hay tres tablas:

  • El "article" mesa
    • clave principal = id
  • El " tag "tabla
    • clave primaria = id
    • contiene los datos de cada etiqueta:
      • nombre, por ejemplo
  • Una tabla "tags_articles", que actúa como una tabla de unión, y sólo contiene:
    • id_article: clave externa que apunta a un artículo
    • id_tag: clave externa que apunta a una etiqueta


De esta manera, no hay duplicación de datos de cualquier etiqueta: para cada etiqueta, hay una, y sólo una, línea en la tabla tag.

Y, para cada artículo, puede tener varias etiquetas (es decir, varias líneas en la tabla tags_articles); y, por supuesto, para cada etiqueta, puede tener varios artículos.

Obtener una lista de etiquetas para un artículo, con esta idea, se trata de una consulta additionnal, como:

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


Obtención de los tres "más similar" artículos significaría:

  • seleccione los artículos que tienen etiquetas que el primer artículo tiene
  • usar sólo los que tienen el número más importante de etiquetas idénticas

no han sido evaluados, sino una idea podría ser algo que se vería así:

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 

Básicamente, usted:

  • seleccionar los identificadores de artículos para cada etiqueta que está presente en su artículo inicial
    • como hay una unión interna, si un artículo en la base de datos tiene 2 etiquetas que coinciden con la cláusula where, sin el group by cl Ause, habría dos líneas para ese artículo
    • por supuesto, no desea volver a seleccionar el artículo que ya tenía, lo que significa que debe excluirse.
  • pero, como se utiliza group by article.id, habrá sólo una línea por artículo
    • pero usted será capaz de utilizar count, para averiguar cuántas etiquetas de cada artículo tiene en común con la inicial uno
  • entonces, solo es cuestión de ordenar por número de etiquetas, y obtener solo las tres tres líneas.
+0

Sí, pero no respondió mi pregunta principal, ¿cómo obtener 3 artículos más similares? – mfolnovich

+1

@mfolnovich: He editado mi respuesta un par de veces para agregar más información sobre el diseño; y, luego, viendo su comentario, volví a editar, para agregar una posible idea de solución para obtener los 3 artículos más similares. –

1

En primer lugar, querrás utilizar la sugerencia de Pascal MARTIN sobre el diseño de la mesa.

En cuanto a la búsqueda de artículos similares, aquí hay algo para empezar. Teniendo en cuenta que @article_id es el artículo que desea encontrar coincidencias para, y tag1 @, @ tag2, @ tag3 son las etiquetas para ese artículo:

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

sí, pero no respondió a mi pregunta principal, cómo obtener 3 artículos más similares?

Respuesta: Solo busque los mismos ID de etiqueta en la tabla combinada (tags_articles). Reúnelos y crea un patrón.

Por ejemplo: artículo 1 tiene etiquetas: 1,2 artículo 2 tiene tags: 2,3,4 artículo 5 tiene tags: 6,7,2 artículo 7 tiene tags: 7,1,2, 3

Si desea los 3 artículos más similares para el artículo 1, debe buscar las etiquetas 1,2. Encontrará que el Artículo 7 es el más similar y 2 y 5 tienen algunas similitudes.

Cuestiones relacionadas