Tout à ce sujet est assez horrible, vous ne pouvez pas indexer sur quelque chose comme les valeurs "nom" et votre "chemin" vers chaque attribut va varier partout. C'est donc vraiment mauvais pour les requêtes.
Je remarque que vous mentionnez des structures « imbriquées », et vous pouvez toujours vous adapter à cela avec une proposition similaire et quelques balises supplémentaires, mais je veux que vous considériez cet exemple de type « répertoire téléphonique » :
{
"phones": [
{
"type": "Home",
"name" : "Jeff",
"phone" : "123-123-1234"
},
{
"type": "Work",
"name" : "Jeff",
"phone" : "123-123-1234"
},
]
}
Puisqu'il s'agit en fait de sous-documents dans un tableau, les champs comme "nom" partagent toujours le même chemin, donc non seulement vous pouvez les indexer (ce qui sera bon pour les performances), mais la requête est très basique :
db.collection({ "phones.name": "Jeff" })
Cela fait exactement ce dont vous avez besoin en trouvant "Jeff" dans n'importe quelle entrée "nom". Si vous avez besoin d'une hiérarchie, ajoutez des champs dans ces sous-documents pour indiquer la relation parent/enfant que vous pouvez utiliser dans le post-traitement. Ou même comme un chemin matérialisé qui pourrait faciliter vos requêtes.
C'est vraiment la meilleure approche.
Si vous devez vraiment conserver ce type de structure, faites au moins quelque chose comme ça avec le JavaScript qui renflouera lors de la première correspondance en profondeur :
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;
}
)
Le format est une notation abrégée pour le $where
opérateur, ce qui est une très mauvaise nouvelle pour les performances, mais votre structure n'offre pas beaucoup d'autre choix. Dans tous les cas, la fonction doit se répéter dans chaque document imbriqué jusqu'à ce que le "champ" avec la "valeur" soit trouvé.
Pour tout ce qui concerne l'échelle de production, envisagez vraiment de changer la structure en quelque chose qui peut être indexé et accessible rapidement. Le premier exemple devrait vous donner un point de départ. S'appuyer sur JavaScript arbitraire pour les requêtes, comme votre structure actuelle vous y oblige, est une mauvaise nouvelle.