Question

J'ai entendu parler de plusieurs façons d'implémenter le balisage ;utiliser une table de mappage entre TagID et ItemID (cela a du sens pour moi, mais est-il évolutif ?), ajouter un nombre fixe de colonnes TagID possibles à ItemID (cela semble être une mauvaise idée), conserver les balises dans une colonne de texte séparée par des virgules (cela semble fou mais ça pourrait marcher).J'ai même entendu quelqu'un recommander une matrice clairsemée, mais alors, comment les noms de balises grandissent-ils gracieusement ?

Est-ce qu'il me manque une bonne pratique pour les balises ?

Était-ce utile?

La solution

Trois tables (une pour stocker tous les éléments, une pour toutes les balises et une pour la relation entre les deux), correctement indexées, avec des clés étrangères définies s'exécutant sur une base de données appropriée, devraient bien fonctionner et évoluer correctement.

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID

Autres conseils

Normalement, je serais d'accord avec Yaakov Ellis mais dans ce cas particulier, il existe une autre solution viable :

Utilisez deux tableaux :

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

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

Cela présente des avantages majeurs :

Premièrement, cela simplifie grandement le développement :dans la solution à trois tables pour l'insertion et la mise à jour de item tu dois rechercher le Tag tableau pour voir s’il y a déjà des entrées.Ensuite, vous devez les rejoindre avec de nouveaux.Ce n’est pas une tâche anodine.

Cela rend ensuite les requêtes plus simples (et peut-être plus rapides).Il existe trois requêtes principales de base de données que vous effectuerez :Afficher tout Tags pour un Item, dessinez un Tag-Cloud et sélectionnez tous les éléments pour un titre de balise.

Toutes les balises pour un article :

3-Tableau :

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

2-Tableau :

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

Nuage de tags :

3-Tableau :

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

2-Tableau :

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

Articles pour une balise :

3-Tableau :

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

2-Tableau :

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

Mais il y a aussi quelques inconvénients :Cela pourrait prendre plus d'espace dans la base de données (ce qui pourrait entraîner davantage d'opérations sur le disque, ce qui serait plus lent) et n'est pas normalisé, ce qui pourrait entraîner des incohérences.

L’argument de la taille n’est pas si fort car la nature même des balises est qu’elles sont normalement assez petites, donc l’augmentation de la taille n’est pas importante.On pourrait affirmer que la requête pour le titre de la balise est beaucoup plus rapide dans une petite table qui ne contient chaque balise qu'une seule fois et cela est certainement vrai.Mais si l’on prend en compte les économies liées au fait de ne pas avoir à adhérer et le fait que vous pouvez construire un bon indice sur eux, cela pourrait facilement compenser cela.Bien entendu, cela dépend fortement de la taille de la base de données que vous utilisez.

L’argument de l’incohérence est également un peu discutable.Les balises sont des champs de texte libre et aucune opération attendue telle que « renommer toutes les balises « foo » en « bar » ».

Alors, attention :J'opterais pour la solution à deux tables.(En fait, je vais le faire.J'ai trouvé cet article pour voir s'il existe des arguments valables contre cela.)

Si vous utilisez une base de données prenant en charge map-reduce, comme couchdb, stocker les balises dans un champ de texte brut ou un champ de liste est en effet le meilleur moyen.Exemple:

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

L'exécuter avec group=true regroupera les résultats par nom de balise et renverra même le nombre de fois où cette balise a été rencontrée.C'est très similaire à compter les occurrences d'un mot dans un texte.

Utilisez une seule colonne de texte formaté[1] pour stocker les balises et utilisez un moteur de recherche en texte intégral performant pour l'indexer.Sinon, vous rencontrerez des problèmes de mise à l'échelle lorsque vous tenterez d'implémenter des requêtes booléennes.

Si vous avez besoin de détails sur les balises dont vous disposez, vous pouvez soit en garder une trace dans une table gérée de manière incrémentielle, soit exécuter une tâche par lots pour extraire les informations.

[1] Certains SGBDR fournissent même un type de tableau natif qui pourrait être encore mieux adapté au stockage en ne nécessitant pas d'étape d'analyse, mais pourrait poser des problèmes avec la recherche en texte intégral.

J'ai toujours conservé les balises dans une table séparée, puis j'ai eu une table de mappage.Bien sûr, je n’ai jamais rien fait à grande échelle non plus.

Avoir une table "tags" et une table de cartes rend assez trivial la génération de nuages ​​​​de tags, etc., car vous pouvez facilement assembler SQL pour obtenir une liste de balises avec le nombre de fois où chaque balise est utilisée.

Je suggérerais le design suivant :Tableau des articles :ID d'article, liste de balises1, liste de balises2
cela sera rapide et facilitera la sauvegarde et la récupération des données au niveau de l'article.

En parallèle construisez une autre table :TAGS TAG NE FAIT PAS L'identifiant unique de la balise et si vous manquez d'espace dans la 2ème colonne qui contient, disons que 100 éléments créent une autre ligne.

Désormais, lors de la recherche d'éléments pour une balise, ce sera très rapide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top