La première chose que vous voulez décider est exactement quel type d'arbre vous allez utiliser.
La grande chose à considérer est vos données et vos modèles d'accès. Vous avez déjà indiqué que 90% de tous vos travaux seront interrogés et que les mises à jour (e-commerce) ne seront effectuées par les administrateurs que très rarement.
Donc vous voulez un schéma qui vous donne le pouvoir d'interroger rapidement sur l'enfant à travers un chemin, à savoir: Sports -> Basketball -> Hommes, Sports -> Tennis -> Femmes, et n'a pas vraiment besoin d'échelle aux mises à jour.
Comme vous l'avez si justement souligné, MongoDB possède une bonne page de documentation: http://docs.mongodb.org/manual/tutorial/model-tree-structures/ où 10gen énonce des modèles et des méthodes de schémas différents pour les arbres et en décrit les principaux hauts et bas.
Celui qui devrait attirer l'attention si vous êtes à la recherche d'interroger les chemins se matérialise facilement: http://docs.mongodb.org/manual/tutorial/model-tree-structures/#model-tree-structures-with-materialized-paths
C'est une méthode très intéressante pour construire des arbres depuis pour interroger l'exemple que vous avez donné ci-dessus dans « Femmes » dans « Tennis » vous pouvez simplement faire une regex pré-fixe (qui peut utiliser l'index: http://docs.mongodb.org/manual/reference/operator/regex/) comme ceci:
db.products.find({category: /^Sports,Tennis,Womens[,]/})
pour trouver tous les produits énumérés sous un certain chemin de votre arbre.
Malheureusement ce modèle est vraiment mauvais à mettre à jour, si vous déplacez une catégorie ou changez son nom vous devez mettre à jour tous les produits et il pourrait y avoir des milliers de produits dans une catégorie.
Une meilleure méthode serait de loger un cat_id
sur le produit, puis séparer les catégories dans une collection séparée avec le schéma:
{
_id: ObjectId(),
name: 'Women\'s',
path: 'Sports,Tennis,Womens',
normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}
Alors maintenant vos requêtes ne concernent que la collection des catégories qui devrait leur faire beaucoup plus petit et plus performant. L'exception à ceci est quand vous supprimez une catégorie, les produits auront toujours besoin de toucher.
Ainsi, un exemple de changement « Tennis » à « Badmin »:
db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
doc.path = doc.path.replace(/,Tennis/, ",Badmin");
db.categories.save(doc);
});
Malheureusement MongoDB fournit pas dans requête le document de réflexion au moment afin que vous ne devez les retirer côté client qui est un peu ennuyeux, mais j'espère que cela ne devrait pas entraîner le retour de trop de catégories.
Et c'est fondamentalement comment cela fonctionne vraiment. C'est un peu difficile à mettre à jour, mais le pouvoir d'interroger instantanément n'importe quel chemin à l'aide d'un index est plus adapté à votre scénario, je crois.
Bien sûr, l'avantage supplémentaire est que ce schéma est compatible avec les modèles de jeux imbriqués: http://en.wikipedia.org/wiki/Nested_set_model que j'ai trouvé à maintes reprises sont tout simplement génial pour les sites de commerce électronique, par exemple, Tennis pourrait être à la fois "Sports" et "Loisirs" et vous voulez plusieurs chemins en fonction de l'origine de l'utilisateur.
Le schéma pour les chemins matérialisés supporte facilement cela en ajoutant simplement un autre path
, aussi simple que cela.
Espérons que cela a du sens, assez long.
Les chemins matérialisés sont robustes à l'interrogation tandis que plus lent à la mise à jour – Sammaye
le lien mongodb docs répertorie cinq approches, pas une et je pense que la troisième semble parfaitement adaptée à votre cas d'utilisation. –