Domanda

Ho sentito parlare di alcuni modi per implementare il tagging;utilizzando una tabella di mappatura tra TagID e ItemID (ha senso per me, ma è scalabile?), aggiungendo un numero fisso di possibili colonne TagID a ItemID (sembra una cattiva idea), mantenendo i tag in una colonna di testo separata da virgole (sembra pazzesco ma potrebbe funzionare).Ho persino sentito qualcuno consigliare una matrice sparsa, ma come fanno i nomi dei tag a crescere con grazia?

Mi manca una best practice per i tag?

È stato utile?

Soluzione

Tre tabelle (una per archiviare tutti gli elementi, una per tutti i tag e una per la relazione tra i due), adeguatamente indicizzate, con chiavi esterne impostate in esecuzione su un database appropriato, dovrebbero funzionare bene e adattarsi correttamente.

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID

Altri suggerimenti

Normalmente sarei d'accordo con Yaakov Ellis ma in questo caso speciale c'è un'altra soluzione praticabile:

Utilizza due tabelle:

Table: Item
Columns: ItemID, Title, Content
Indexes: ItemID

Table: Tag
Columns: ItemID, Title
Indexes: ItemId, Title

Ciò presenta alcuni vantaggi importanti:

Innanzitutto rende lo sviluppo molto più semplice:nella soluzione a tre tabelle per l'inserimento e l'aggiornamento del item devi cercare il Tag tabella per vedere se sono già presenti voci.Quindi devi unirti a loro con quelli nuovi.Questo non è un compito banale.

Quindi rende le query più semplici (e forse più veloci).Ci sono tre principali query sul database che farai:Emetti tutto Tags per uno Item, disegna una nuvola di tag e seleziona tutti gli elementi per un titolo di tag.

Tutti i tag per un articolo:

3-Tabella:

SELECT Tag.Title 
  FROM Tag 
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 WHERE ItemTag.ItemID = :id

2-Tabella:

SELECT Tag.Title
FROM Tag
WHERE Tag.ItemID = :id

Tag Cloud:

3-Tabella:

SELECT Tag.Title, count(*)
  FROM Tag
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 GROUP BY Tag.Title

2-Tabella:

SELECT Tag.Title, count(*)
  FROM Tag
 GROUP BY Tag.Title

Articoli per un tag:

3-Tabella:

SELECT Item.*
  FROM Item
  JOIN ItemTag ON Item.ItemID = ItemTag.ItemID
  JOIN Tag ON ItemTag.TagID = Tag.TagID
 WHERE Tag.Title = :title

2-Tabella:

SELECT Item.*
  FROM Item
  JOIN Tag ON Item.ItemID = Tag.ItemID
 WHERE Tag.Title = :title

Ma ci sono anche alcuni inconvenienti:Potrebbe richiedere più spazio nel database (il che potrebbe portare a più operazioni sul disco, il che è più lento) e non è normalizzato, il che potrebbe portare a incoerenze.

L'argomento relativo alle dimensioni non è così forte perché la natura stessa dei tag è che normalmente sono piuttosto piccoli, quindi l'aumento delle dimensioni non è grande.Si potrebbe sostenere che la query per il titolo del tag è molto più veloce in una piccola tabella che contiene ciascun tag solo una volta e questo è certamente vero.Ma tenendo conto dei risparmi derivanti dal non dover aderire e del fatto che è possibile creare un buon indice su di essi, si potrebbe facilmente compensare questo problema.Questo ovviamente dipende molto dalla dimensione del database che stai utilizzando.

Anche l’argomento dell’incoerenza è un po’ controverso.I tag sono campi di testo liberi e non è prevista alcuna operazione come "rinominare tutti i tag da "foo" a "bar"".

Quindi tldr:Io opterei per la soluzione a due tavoli.(Infatti lo farò.Ho trovato questo articolo per vedere se ci sono argomenti validi contro di esso.)

Se stai utilizzando un database che supporta la riduzione delle mappe, come couchdb, memorizzare i tag in un campo di testo semplice o in un campo elenco è davvero il modo migliore.Esempio:

tagcloud: {
  map: function(doc){ 
    for(tag in doc.tags){ 
      emit(doc.tags[tag],1) 
    }
  }
  reduce: function(keys,values){
    return values.length
  }
}

Eseguendo questo con group=true raggrupperà i risultati per nome del tag e restituirà anche un conteggio del numero di volte in cui il tag è stato incontrato.È molto simile a contare le occorrenze di una parola nel testo.

Utilizza una singola colonna di testo formattato[1] per memorizzare i tag e utilizza un motore di ricerca full-text capace per indicizzarla.Altrimenti ti imbatterai in problemi di ridimensionamento quando provi a implementare query booleane.

Se hai bisogno di dettagli sui tag che hai, puoi tenerne traccia in una tabella mantenuta in modo incrementale o eseguire un lavoro batch per estrarre le informazioni.

[1] Alcuni RDBMS forniscono anche un tipo di array nativo che potrebbe essere ancora più adatto per l'archiviazione poiché non necessita di una fase di analisi, ma potrebbe causare problemi con la ricerca del testo completo.

Ho sempre mantenuto i tag in una tabella separata e poi ho avuto una tabella di mappatura.Naturalmente non ho mai fatto nulla su larga scala.

Avere una tabella "tag" e una tabella della mappa rende piuttosto banale generare tag cloud e simili poiché puoi facilmente mettere insieme SQL per ottenere un elenco di tag con il conteggio della frequenza con cui viene utilizzato ciascun tag.

Suggerirei il seguente design:Tabella degli articoli:ID articolo, taglista1, taglista2
questo sarà veloce e faciliterà il salvataggio e il recupero dei dati a livello di articolo.

In parallelo costruisci un'altra tabella:Tag tag non rendere l'identificatore univoco di tag e se si esaurisce lo spazio in 2a colonna che contiene, diciamo 100 elementi Creare un'altra riga.

Ora la ricerca degli elementi per un tag sarà super veloce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top