Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Pesquisa no MongoDB

Pessoal,

No exercício proposto, digamos que eu insira os seguintes registros na minha coleção alunos:

db.alunos.insert({
    "nome": "Felipe",
    "data_nascimento": new Date(1994, 02, 26),
    "notas": [10, 9, 4.5],
    "curso": {
        "nome": "Sistemas de informação"
    },
    "habilidades": [
        {
            "nome": "Inglês",
            "nível": "Avançado"
        }
    ]
})

db.alunos.insert({
    "nome": "Paulo",
    "data_nascimento": new Date(1979, 12, 31),
    "notas": [10, 9, 7],
    "curso": {
        "nome": "Ciências da computação"
    },
    "habilidades": [
        {
            "nome": "Inglês",
            "nível": "Básico"
        },
        {
            "nome": "Espanhol",
            "nível": "Avançado"
        }
    ]
})

Se eu consultar db.alunos.find({"habilidades.nome":"inglês"}), terei todos os alunos que falam inglês (Felipe e Paulo).

Minha dúvida: como restringir a pesquisa para trazer apenas os alunos que tenham inglês avançado (somente Felipe)?

Não posso incluir qualquer {"habilidades.nível":"avançado"}, pois isto também traria o Paulo, que tem Espanhol avançado.

Obrigado!

8 respostas

Elton, vc chegou a tentar algo desse tipo:

db.alunos.find({
    "habilidades.nome":"inglês",
    "habilidades.nível":"avançado"
})

Eu usei Mongo faz um tempo já, não tenho certeza desse código, mas eu tentaria (:

Se não funcionar dá um toque instalo aqui e tento ver pra vc!

Abraço!

Yuri,

Na verdade esse foi o primeiro teste que fiz. O problema é que esta consulta traz todos os alunos que tiverem qualquer habilidade em nível avançado: inglês, espanhol, judô...

No exemplo acima, ele vai trazer tanto o Felipe (que tem inglês avançado); quanto o Paulo (que tem o espanhol avançado).

Enfim, queria saber se há alguma alternativa sem ter que alterar a modelagem proposta no curso...

Obrigado!

Ahh sim, isso faz um AND lógico, então essa query traria quem tem:

habilidade em inglês && nível avançado

Sendo assim os resultados teriam que ter habilidade em inglês, de qualquer nível, e nível avançado, em qualquer habilidade, por isso ele trás mais resultados do que deveria pra gente! (:

Faz outro teste? Tenta isso:

{
    $and: [
         {"habilidades.nome":"inglês"},
         {"habilidades.nível":"avançado"}
    ]
}

O problema é que ele tem que cruzar as informações no mesmo objeto, vamos ver se assim vai.

Abraço!

Yuri, ainda não foi nessa!

O resultado foi similar ao anterior: a consulta com o $and trouxe todos os alunos quem possuem alguma habilidade avançada!

Alguma luz do que fazer Elton? Fiquei pensando aqui mais um pouco e cheguei nisso aqui:

db.alunos.habilidades.find({
    "nome":"inglês",
    "nível":"avançado"
});

Já testou?

Yuri, tentei agora o db.alunos.habilidades.find(), não retornou nada...

solução!

Olá Elton, Tudo bom?

Quando o campo a ser pesquisado é um array de objetos existem alguns detalhes para serem observados:

Quando você faz

{
    "nome":"inglês",
    "nível":"avançado"
};

ou

{
    $and: [
         {"habilidades.nome":"inglês"},
         {"habilidades.nível":"avançado"}
    ]
}

você está dizendo para procurar dentro daquele array documentos com o nome Inglês e o nível Avançado MAS não necessariamente no mesmo documento.

Para restringir a pesquisa ao mesmo documento deve ser usado o operador $elemMatch.

A forma correta seria: db.alunos.find({"habilidades": { $elemMatch: { "nível": "Avançado", "nome": "Inglês" } }})

Dá uma olhada nesse link: https://docs.mongodb.com/manual/tutorial/query-array-of-documents/#a-single-nested-document-meets-multiple-query-conditions-on-nested-fields

abc

Obrigado Arthur, o $elemMatch fez a pesquisa que eu queria!