MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Maneira mais eficiente de armazenar categorias aninhadas (ou dados hierárquicos) no Mongo?


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á.