2015-10-17 4 views
5

MongoDBを使用して、リスト内の少なくとも1つの項目が検索パラメータと一致するリストを含む要素を検索しています。MongoDBリストのリストの値

これは私が現在持っている構造の例です。

{ 
    "Item 1":{ 
     "data":[ 
     ["green", 1] 
     ] 
    }, 
    "Item 2":{ 
     "data":[ 
     ["blue", 9], 
     ["green", 1] 
     ] 
    } 
} 

私はデータリストに値「グリーン」を持っているすべての項目を検索したいです。

私は現在、このている:

my_data.find({'data': {'$in': ['green']}}) 

しかし、何も結果が返されません。

+1

をテストするだけで、そのパスのための1つのcondtionすることができますこれは役に立ちます。 http://stackoverflow.com/questions/17303833/mongodb-nested-array-query – lostintranslation

答えて

5

ここで検索する必要があるパスの「トップレベル」ではなく、「アイテム1」または「アイテム2」です"と"データ "はその中のサブ要素です。

基本的なケースは、ルート要素が少なくとも「存在する」ことが知られている"dot notation"を使用することです。また、$in演算子はMongoDBが気にしないので、配列内の値を照合するだけでよいことにも注意してください。しかし、あなたは代わりに、ネストされた$elemMatchが必要になります。

db.my_data.find({ 
    "$or": [ 
     { "Item 1.data": { 
      "$elemMatch": { 
       "$elemMatch": { "$eq": "green" } 
      } 
     }}, 
     { "Item 2.data": { 
      "$elemMatch": { 
       "$elemMatch": { "$eq": "green" } 
      } 
     }} 
    ] 
}) 

各可能なパスを検索する$or条件内の完全なパスを述べることが必要であるので、先行パスの一部に一致するための「ワイルドカード」はありません資料。

可能なすべての接頭辞のキーを書くことは、あなたの唯一の他のアプローチは、マッチングのための論理を決定するために$whereでJavaScriptの評価を使用している、実用的ではない場合:

db.my_data.find(function() { 
    var doc = this; 
    delete doc._id; 

    var matched = false; 
    for (k in doc) { 
     matched = doc[k].data.some(function(el) { 
      return el.some(function(inner) { 
       return inner === "green"; 
      }); 
     }); 
     if (matched) break; 
    } 
    return matched; 
}) 

か、そのロジックのいくつかのバリエーション実際に可能テストしますあなたの "緑の"値を格納する "データ"配列を持つ要素。 $whereは、条件を評価するために各ドキュメントで実行する必要があり、インデックスを使用して結果をフィルタリングすることはできないため、優れたソリューションではありません。これはコレクション全体をスキャンすることを意味し、基本的には最も遅いアプローチです。

また、function()の内容は、pymongoや他の言語ドライバの場合、$whereの引数に "string"として送信されますが、基本的なコンテキストは、そのJavaScriptコードですサーバー上で評価されます。

さらに、ドキュメントを変更して、照会する要素に常に一貫したパスがあるようにします。以下のような:

{ 
    "items": [ 
     { "name": "Item 1", "data": [["green", 1]] }, 
     { "name": "Item 2", "data": [["blue", 9], ["green", 1]] } 
    ] 
} 

次に、あなただけのこの単純なクエリを発行することができます:「パス」として

db.my_data.find({ "items.data": { "$elemMatch": { "$elemMatch": { "$eq": "green" } } } }) 

を常に"items.data"で、これはすべての要素

+0

本当に包括的な答えをいただきありがとうございます。これは大きな助けとなりました。 – Gunther

関連する問題