Conception de firebase database SQL recommandée pour les balises ou le marquage

J’ai entendu parler de quelques façons de mettre en œuvre le marquage; utiliser une table de correspondance entre TagID et ItemID (cela a du sens pour moi, mais est-ce que cela évolue?), append un nombre fixe de colonnes TagID possibles à ItemID (semble être une mauvaise idée) fou mais pourrait travailler). J’ai même entendu quelqu’un recommander une masortingce clairsemée, mais comment les noms d’étiquettes se développent-ils avec grâce?

Est-ce que je manque une meilleure pratique pour les tags?

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 sur une firebase database appropriée, devraient fonctionner correctement et évoluer correctement.

Table: Item Columns: ItemID, Title, Content Table: Tag Columns: TagID, Title Table: ItemTag Columns: ItemID, TagID 

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

Utilisez deux tables:

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

Cela présente des avantages majeurs:

Tout d’abord, le développement est beaucoup plus simple: dans la solution à trois tables pour l’insertion et la mise à jour de l’ item vous devez rechercher la table Tag pour voir s’il existe déjà des entrées. Ensuite, vous devez les rejoindre avec de nouveaux. Ce n’est pas une tâche sortingviale.

Ensuite, les requêtes sont plus simples (et peut-être plus rapides). Vous devez effectuer trois requêtes principales dans la firebase database: Imprimez tous les Tags pour un Item , dessinez un tag-cloud et sélectionnez tous les éléments pour un seul titre.

Tous les tags pour un article:

3-table:

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

2-table:

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

Tag-Cloud:

3-table:

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

2-table:

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

Articles pour un tag:

3-table:

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

2-table:

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

Mais il ya aussi des inconvénients: cela pourrait prendre plus d’espace dans la firebase database (ce qui pourrait ralentir le nombre d’opérations sur le disque) et cela n’est pas normalisé, ce qui pourrait entraîner des incohérences.

L’argument de la taille n’est pas si fort que la nature même des tags est qu’ils sont normalement assez petits, donc l’augmentation de la taille n’est pas importante. On pourrait soutenir que la requête pour le titre de la balise est beaucoup plus rapide dans une petite table qui contient chaque balise une seule fois et cela est certainement vrai. Mais prendre en compte les économies réalisées pour ne pas avoir à adhérer et le fait de pouvoir créer un bon index peut facilement compenser cela. Cela dépend bien entendu de la taille de la firebase database que vous utilisez.

L’argument d’incohérence est un peu compliqué aussi. Les balises sont des champs de texte libre et il n’y a pas d’opération attendue comme “renommer toutes les balises” foo “en” bar “‘.

Tldr: J’irais pour la solution à deux tables. (En fait, je vais à. J’ai trouvé cet article pour voir s’il y a des arguments valables contre cela.)

Si vous utilisez une firebase database prenant en charge la réduction de carte, comme couchdb, le stockage de balises dans un champ de texte brut ou dans 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 retournera 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 le texte .

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

Si vous avez besoin de détails sur les balises dont vous disposez, vous pouvez soit les conserver dans un tableau à gestion incrémentielle, soit exécuter un traitement 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’parsing, mais pourrait entraîner des problèmes lors de la recherche en texte intégral.

J’ai toujours conservé les balises dans un tableau séparé et disposait d’une table de correspondance. Bien sûr, je n’ai jamais rien fait à grande échelle non plus.

Avoir une table “tags” et une table de cartes rend très simple la génération de nuages ​​de tags, car vous pouvez facilement assembler SQL pour obtenir une liste de tags avec le nombre de fois où chaque tag est utilisé.

Je suggère la conception suivante: Item Table: Itemid, taglist1, taglist2
Cela sera rapide et permettra d’enregistrer et de récupérer facilement les données au niveau de l’article.

En parallèle, créez une autre table: les balises tag ne font pas l’identifiant unique de la balise et si vous manquez d’espace dans la 2ème colonne qui contient, disons, 100 éléments créent une autre ligne.

Maintenant, tout en recherchant des éléments pour un tag, il sera super rapide.