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

Otimização de consultas MongoDB


O que você quer é um resultado de "pesquisa facetada" onde você mantém as estatísticas sobre os termos correspondentes no conjunto de resultados atual. Subsequentemente, embora existam produtos que "parecem" fazer todo o trabalho em uma única resposta, você deve considerar que a maioria dos mecanismos de armazenamento genéricos precisará de várias operações.

Com o MongoDB, você pode usar duas consultas para obter os próprios resultados e outra para obter as informações das facetas. Isso daria resultados semelhantes aos resultados facetados disponíveis em produtos de mecanismos de pesquisa dedicados, como Solr ou ElasticSearch.

Mas para fazer isso de forma eficaz, você deseja incluir isso em seu documento de uma forma que possa ser usado de forma eficaz. Uma forma muito eficaz para o que você deseja é usar uma matriz de dados tokenizados:
 {
     "otherData": "something",
     "facets": [
         "country:UK",
         "city:London-UK",
         "genre:Student"
     ]
 }

Portanto, "factets" é um único campo em seu documento e não em vários locais. Isso torna muito fácil indexar e consultar. Em seguida, você pode agregar efetivamente seus resultados e obter os totais de cada faceta:
User.aggregate(
    [
        { "$unwind": "$facets" },
        { "$group": {
            "_id": "$facets",
            "count": { "$sum": 1 }
        }}
    ],
    function(err,results) {

    }
);

Ou melhor, com alguns critérios em $match :
User.aggregate(
    [
        { "$match": { "facets": { "$in": ["genre:student"] } } },
        { "$unwind": "$facets" },
        { "$group": {
            "_id": "$facets",
            "count": { "$sum": 1 }
        }}
    ],
    function(err,results) {

    }
);

Em última análise, dando uma resposta como:
{ "_id": "country:FR", "count": 50 },
{ "_id": "country:UK", "count": 300 },
{ "_id": "city:London-UK", "count": 150 },
{ "_id": "genre:Student": "count": 500 }

Essa estrutura é fácil de percorrer e inspecionar coisas como o "país" discreto e a "cidade" que pertence a um "país", pois esses dados são separados de forma consistente por um hífen "-".

Tentar misturar documentos dentro de arrays é uma má ideia. Há um limite de tamanho BSON de 16 MB a ser respeitado também, a partir do qual os resultados combinados (especialmente se você estiver tentando manter o conteúdo do documento) certamente acabarão sendo excedidos na resposta.

Para algo tão simples como obter a "contagem geral" de resultados de tal consulta, basta somar os elementos de um tipo de faceta específico. Ou apenas emita seus mesmos argumentos de consulta para um .count() Operação:
User.count({ "facets": { "$in": ["genre:Student"] } },function(err,count) {

});

Como dito aqui, particularmente ao implementar "paginação" de resultados, as funções de obter "Contagem de resultados", "Contagem de facetas" e a "Página de resultados" real são todas delegadas para consultas "separadas" ao servidor.

Não há nada de errado em enviar cada uma dessas consultas ao servidor em paralelo e depois combinar uma estrutura para alimentar seu modelo ou aplicativo muito parecido com o resultado de pesquisa facetado de um dos produtos de mecanismo de pesquisa que oferece esse tipo de resposta.

Concluindo


Então coloque algo em seu documento para marcar as facetas em um único lugar. Uma matriz de strings tokenizadas funciona bem para essa finalidade. Também funciona bem com formulários de consulta como $in e $all para as condições "ou" ou "e" em combinações de seleção de facetas.

Não tente misturar resultados ou aninhar adições apenas para corresponder a alguma estrutura hierárquica percebida, mas sim percorrer os resultados recebidos e usar padrões simples nos tokens. É muito simples

Execute consultas paginadas para o conteúdo como consultas separadas para facetas ou contagens gerais. Tentar empurrar todo o conteúdo em arrays e depois limitar apenas para obter contagens não faz sentido. O mesmo se aplicaria a uma solução RDBMS para fazer a mesma coisa, onde as contagens de resultados de paginação e a página atual são operações de consulta separadas.

Há mais informações escritas no Blog do MongoDB sobre Pesquisa Facetada com MongoDB que também explica algumas outras opções. Há também artigos sobre integração com soluções de pesquisa externas usando mongoconnector ou outras abordagens.