これに関するすべてはかなり恐ろしいものであり、「名前」の値のようなものにインデックスを付けることはできず、各属性への「パス」はどこでも変化します。したがって、これはクエリにとって非常に悪いことです。
「ネストされた」構造について言及していることに気付きました。同様の提案といくつかの追加のタグ付けでこれに対応できますが、この「電話帳」タイプの例を検討してください。
{
"phones": [
{
"type": "Home",
"name" : "Jeff",
"phone" : "123-123-1234"
},
{
"type": "Work",
"name" : "Jeff",
"phone" : "123-123-1234"
},
]
}
これは実際には配列内のサブドキュメントであるため、「name」などのフィールドは常に同じパスを共有します。したがって、これらにインデックスを付けることができるだけでなく(パフォーマンスに役立つ)、クエリは非常に基本的です。
db.collection({ "phones.name": "Jeff" })
これは、任意の「名前」エントリで「Jeff」を見つけることにより、まさに必要なことを実行します。階層が必要な場合は、後処理で使用できる親子関係を示すために、これらのサブドキュメントにいくつかのフィールドを追加します。または、クエリを支援する可能性のある具体化されたパスとしても。
それは本当に良いアプローチです。
本当にこの種の構造を維持する必要がある場合は、少なくともJavaScriptを使用してこのようなことを行い、最初の一致で詳細に解決します。
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;
}
)
$where
演算子。これはパフォーマンスにとってはかなり悪いニュースですが、構造は他の選択肢をあまり提供していません。いずれにせよ、関数は、「値」を持つ「フィールド」が見つかるまで、ネストされた各ドキュメントに再帰する必要があります。
実稼働規模の場合は、構造をインデックスに登録してすばやくアクセスできるものに変更することを実際に検討してください。最初の例はあなたに出発点を与えるはずです。現在の構造では制約があるため、クエリを任意のJavaScriptに依存するのは悪いニュースです。