A primeira coisa que você quer decidir é exatamente que tipo de árvore você usará.
A grande coisa a considerar são seus dados e padrões de acesso. Você já afirmou que 90% de todo o seu trabalho será de consulta e pelo que parece (e-commerce) as atualizações serão executadas apenas por administradores, provavelmente raramente.
Então você quer um esquema que lhe dê o poder de consultar rapidamente no filho através de um caminho, ou seja:Esportes -> Basquete -> Masculino, Esportes -> Tênis -> Feminino, e não precisa realmente dimensionar para atualizações.
Como você apontou, o MongoDB tem uma boa página de documentação para isso:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ em que 10gen realmente declara diferentes modelos e métodos de esquema para árvores e descreve os principais altos e baixos deles.
O que deve chamar a atenção se você estiver procurando facilmente são os caminhos materializados:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/
Este é um método muito interessante para construir árvores, pois para consultar o exemplo que você deu acima em "Mulheres" em "Tênis" você pode simplesmente fazer um regex pré-fixado (que pode usar o índice:http://docs.mongodb.org/manual/reference/operator/regex/ ) igual a:
db.products.find({category: /^Sports,Tennis,Womens[,]/})
para encontrar todos os produtos listados em um determinado caminho de sua árvore.
Infelizmente, este modelo é muito ruim em atualizar, se você mover uma categoria ou alterar seu nome, precisará atualizar todos os produtos e poderá haver milhares de produtos em uma categoria.
Um método melhor seria hospedar um
cat_id
no produto e, em seguida, separe as categorias em uma coleção separada com o esquema:{
_id: ObjectId(),
name: 'Women\'s',
path: 'Sports,Tennis,Womens',
normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}
Portanto, agora suas consultas envolvem apenas a coleção de categorias, o que deve torná-las muito menores e com melhor desempenho. A exceção a isso é quando você exclui uma categoria, os produtos ainda precisarão ser tocados.
Então, um exemplo de mudança de "Tennis" para "Badmin":
db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
doc.path = doc.path.replace(/,Tennis/, ",Badmin");
db.categories.save(doc);
});
Infelizmente, o MongoDB não fornece nenhuma reflexão de documento na consulta no momento, então você precisa retirá-los do lado do cliente, o que é um pouco irritante, mas esperamos que não resulte em muitas categorias sendo trazidas de volta.
E é basicamente assim que funciona realmente. É um pouco trabalhoso atualizar, mas o poder de poder consultar instantaneamente em qualquer caminho usando um índice é mais adequado para o seu cenário, acredito.
Claro que o benefício adicional é que este esquema é compatível com modelos de conjuntos aninhados:http://en.wikipedia .org/wiki/Nested_set_model que eu descobri uma e outra vez são simplesmente incríveis para sites de comércio eletrônico, por exemplo, o tênis pode estar em "Esportes" e "Lazer" e você deseja vários caminhos, dependendo de onde o usuário veio.
O esquema para caminhos materializados suporta isso facilmente apenas adicionando outro
path
, que simples. Espero que faça sentido, bastante longo lá.