Come progettare una tabella MySQL per un Tag Cloud?
-
25-09-2019 - |
Domanda
Ho articoli sul mio sito, e vorrei aggiungere tag che descrivono ogni articolo, ma sto avendo problemi con la tabella dati mysql per i tag. Ho due idee:
- ogni articolo avrebbe campo "tag" e tag sarebbe in formato: "tag1, tag2, tag3"
- creare altri tag table chiamato con i campi: tag_name, article_id
Così, quando voglio tag per articolo con ID 1, vorrei correre
SELECT ... FROM tags WHERE `article_id`=1;
Ma, mi piace anche sapere 3 articoli più simili confrontando i tag, quindi se ho un articolo che ha tag "php, mysql, Erlang", e 5 articoli con tag: "php, mysql", "Erlang, ruby", "php Erlang", "mysql, Erlang, javascript", sceglierei 1., 3. e 4., dal momento che coloro che hanno la maggior parte 3 stessi tag con l'articolo principale.
Inoltre altra domanda, qual è il modo migliore per ottenere 10 "Tag più usate"?
Soluzione
In generale, per questo tipo di molti-a-molti, ci sono tre tabelle:
- La tabella "
article
"- chiave primaria = id
- La tabella "
tag
"- chiave primaria = id
- contiene i dati di ogni tag:
- nome, ad esempio
- Una tabella "
tags_articles
", che agisce come un join tavolo, e contiene solo:-
id_article
: chiave esterna che punta a un articolo -
id_tag
: chiave esterna che punta a un tag
-
In questo modo, non v'è alcuna duplicazione dei dati di ogni tag:. Per ogni tag, ce n'è uno, e solo uno, riga nella tabella tag
E, per ogni articolo, è possibile avere diversi tag (cioè diverse righe della tabella tags_articles
); e, naturalmente, per ogni tag, è possibile avere diversi articoli.
Ottenere un elenco di tag per un articolo, con questa idea, è una questione di una query additionnal, come:
select tag.*
from tag
inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123
Ottenere i tre "la maggior parte degli articoli simili" significherebbe:
- selezionare gli articoli che hanno tag che il primo articolo ha
- utilizzare solo quelle che hanno il maggior numero importante di tag identiche
Non testato, ma un'idea potrebbe essere qualcosa che sarebbe simile a questa:
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
In sostanza, è:
- selezionare gli articoli ID per ogni tag che è presente sul vostro articolo iniziale
- in quanto v'è un inner join, se un articolo del DB ha 2 tag che corrispondono alla clausola
where
, senza la clausolagroup by
, ci sarebbero due linee per questo articolo - , naturalmente, non si vuole riselezionare l'articolo che hai già avuto -. Che significa che deve essere esclusa
- in quanto v'è un inner join, se un articolo del DB ha 2 tag che corrispondono alla clausola
- , ma, come si usa
group by article.id
, ci sarà solo una riga per ogni articolo- , ma sarete in grado di utilizzare
count
, per scoprire quanti tag ogni articolo ha in comune con quella iniziale
- , ma sarete in grado di utilizzare
- allora, è solo una questione di selezione per numero di tag, e ottenendo solo il terzo tre linee.
Altri suggerimenti
Prima di tutto, ti consigliamo di utilizzare il suggerimento di Pascal MARTIN circa la struttura della tabella.
Per quanto riguarda la ricerca di articoli simili, di qui qualcosa per iniziare. Dato che @article_id è l'articolo che si desidera trovare corrispondenze per e @ tag1, @ tag2, @ tag3 sono i tag per questo articolo:
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
Sì, ma non hai risposto alla mia domanda principale, come ottenere 3 articoli più simili?
Risposta: Basta guardare per gli stessi ID di tag nella tabella risultante dalla fusione (tags_articles). raccoglierle e creare un modello.
Ad esempio: Articolo 1 ha tags: 1,2 Articolo 2 ha tags: 2,3,4 Articolo 5 ha tags: 6,7,2 Articolo 7 ha tags: 7,1,2,3
Se si desidera che i 3 articoli più simile per l'articolo 1, si deve guardare per i tag 1,2. Troverete l'articolo 7, che è più simile e 2 e 5 hanno alcune somiglianze.