Tudo sobre isso é bastante horrível, você não pode indexar em algo como os valores de "nome" e seu "caminho" para cada atributo varia em todos os lugares. Então isso é muito ruim para consultas.
Percebo que você mencionou estruturas "aninhadas" e ainda pode acomodar isso com uma proposta semelhante e algumas tags adicionais, mas quero que você considere este exemplo do tipo "lista telefônica":
{
"phones": [
{
"type": "Home",
"name" : "Jeff",
"phone" : "123-123-1234"
},
{
"type": "Work",
"name" : "Jeff",
"phone" : "123-123-1234"
},
]
}
Como na verdade são subdocumentos em uma matriz, campos como "nome" sempre compartilham o mesmo caminho, portanto, você não apenas pode indexá-los (o que será bom para o desempenho), mas a consulta é muito básica:
db.collection({ "phones.name": "Jeff" })
Isso faz exatamente o que você precisa encontrando "Jeff" em qualquer entrada de "nome". Se você precisar de uma hierarquia, adicione alguns campos nesses subdocumentos para indicar o relacionamento pai/filho que você pode usar no pós-processamento. Ou mesmo como um caminho materializado que pode auxiliar suas consultas.
Realmente é a melhor abordagem.
Se você realmente deve manter esse tipo de estrutura, pelo menos faça algo assim com o JavaScript que vai sair da primeira partida em profundidade:
db.collection.find(
function () {
var found = false;
var finder = function( obj, field, value ) {
if ( obj.hasOwnProperty(field) && obj[field] == value )
found = true;
if (found) return true;
for( var n in obj ) {
if ( Object.prototype.toString.call(obj[n]) === "[object Object]" ) {
finder( obj[n], field, value );
if (found) return true;
}
}
};
finder( this, "name", "Jeff" );
return found;
}
)
O formato existe uma notação abreviada para o
$where
operador, o que é uma péssima notícia para o desempenho, mas sua estrutura não oferece muitas outras opções. De qualquer forma, a função deve recorrer em cada documento aninhado até que o "campo" com o "valor" seja encontrado. Para qualquer coisa de escala de produção, realmente procure mudar a estrutura para algo que possa ser indexado e acessado rapidamente. O primeiro exemplo deve lhe dar um ponto de partida. Confiar em JavaScript arbitrário para consultas como sua estrutura atual o restringe é uma má notícia.