Frage

Ich habe von einigen Möglichkeiten gehört, Tagging zu implementieren.Verwenden einer Zuordnungstabelle zwischen TagID und ItemID (macht für mich Sinn, aber ist sie skalierbar?), Hinzufügen einer festen Anzahl möglicher TagID-Spalten zu ItemID (scheint eine schlechte Idee zu sein), Behalten von Tags in einer Textspalte, die durch Kommas getrennt ist (klingt verrückt, könnte aber funktionieren).Ich habe sogar gehört, dass jemand eine Sparse-Matrix empfohlen hat, aber wie wachsen die Tag-Namen dann elegant?

Vermisse ich eine Best Practice für Tags?

War es hilfreich?

Lösung

Drei Tabellen (eine zum Speichern aller Elemente, eine für alle Tags und eine für die Beziehung zwischen beiden), ordnungsgemäß indiziert und mit Fremdschlüsseln, die in einer geeigneten Datenbank ausgeführt werden, sollten gut funktionieren und ordnungsgemäß skaliert werden.

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID

Andere Tipps

Normalerweise würde ich Yaakov Ellis zustimmen, aber in diesem speziellen Fall gibt es eine andere praktikable Lösung:

Verwenden Sie zwei Tabellen:

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

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

Dies hat einige große Vorteile:

Erstens macht es die Entwicklung viel einfacher:in der Drei-Tabellen-Lösung zum Einfügen und Aktualisieren von item Sie müssen nachschlagen Tag Tabelle, um zu sehen, ob bereits Einträge vorhanden sind.Dann muss man ihnen neue hinzufügen.Das ist keine triviale Aufgabe.

Dann werden Abfragen einfacher (und möglicherweise schneller).Es gibt drei Hauptdatenbankabfragen, die Sie durchführen werden:Alles ausgeben Tags für eine Item, zeichnen Sie eine Tag-Wolke und wählen Sie alle Elemente für einen Tag-Titel aus.

Alle Tags für einen Artikel:

3-Tisch:

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

2-Tisch:

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

Tag-Cloud:

3-Tisch:

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

2-Tisch:

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

Artikel für einen Tag:

3-Tisch:

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

2-Tisch:

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

Aber es gibt auch einige Nachteile:Es könnte mehr Speicherplatz in der Datenbank beanspruchen (was zu mehr und langsameren Festplattenvorgängen führen könnte) und es ist nicht normalisiert, was zu Inkonsistenzen führen könnte.

Das Größenargument ist nicht so stark, da es in der Natur von Tags liegt, dass sie normalerweise ziemlich klein sind, sodass die Größenzunahme nicht groß ist.Man könnte argumentieren, dass die Abfrage des Tag-Titels in einer kleinen Tabelle, die jedes Tag nur einmal enthält, viel schneller ist, und das trifft sicherlich zu.Wenn man jedoch die Einsparungen bedenkt, die dadurch entstehen, dass man nicht beitreten muss, und die Tatsache, dass man daraus einen guten Index erstellen kann, könnte dies leicht kompensiert werden.Dies hängt natürlich stark von der Größe der verwendeten Datenbank ab.

Auch das Argument der Inkonsistenz ist ein wenig fraglich.Tags sind Freitextfelder und es gibt keinen erwarteten Vorgang wie „Alle Tags „foo“ in „bar“ umbenennen“.

Also tldr:Ich würde mich für die Zwei-Tisch-Lösung entscheiden.(Tatsächlich werde ich es tun.Ich habe diesen Artikel gefunden, um zu sehen, ob es stichhaltige Argumente dagegen gibt.)

Wenn Sie eine Datenbank verwenden, die Map-Reduce unterstützt, wie z. B. Couchdb, ist das Speichern von Tags in einem Nur-Text-Feld oder Listenfeld tatsächlich die beste Möglichkeit.Beispiel:

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

Wenn Sie dies mit „group=true“ ausführen, werden die Ergebnisse nach Tag-Namen gruppiert und sogar die Anzahl der Treffer dieses Tags zurückgegeben.Es ist sehr ähnlich Zählen der Vorkommen eines Wortes im Text.

Verwenden Sie eine einzelne formatierte Textspalte[1] zum Speichern der Tags und verwenden Sie eine leistungsfähige Volltextsuchmaschine, um diese zu indizieren.Andernfalls treten Skalierungsprobleme auf, wenn Sie versuchen, boolesche Abfragen zu implementieren.

Wenn Sie Details zu Ihren Tags benötigen, können Sie diese entweder in einer inkrementell gepflegten Tabelle verfolgen oder einen Batch-Job ausführen, um die Informationen zu extrahieren.

[1] Einige RDBMS stellen sogar einen nativen Array-Typ bereit, der möglicherweise noch besser für die Speicherung geeignet ist, da kein Parsing-Schritt erforderlich ist, aber Probleme bei der Volltextsuche verursachen kann.

Ich habe die Tags immer in einer separaten Tabelle gespeichert und hatte dann eine Zuordnungstabelle.Natürlich habe ich auch noch nie etwas wirklich Großes gemacht.

Mit einer „Tags“-Tabelle und einer Kartentabelle ist es ziemlich einfach, Tag-Wolken usw. zu generieren, da Sie ganz einfach SQL zusammenstellen können, um eine Liste von Tags mit der Häufigkeit der Verwendung jedes Tags zu erhalten.

Ich würde folgendes Design vorschlagen:Artikeltabelle:Artikel-ID, Taglist1, Taglist2
Dies geht schnell und erleichtert das Speichern und Abrufen der Daten auf Artikelebene.

Erstellen Sie parallel eine weitere Tabelle:Tags Tags erstellen Sie keine eindeutige Bezeichnerin und wenn Ihnen in der 2. Spalte der Platz ausgeht, in dem wir 100 Elemente erstellen, erstellen Sie eine andere Zeile.

Jetzt geht die Suche nach Artikeln für ein Tag superschnell.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top