2016-06-21 5 views
2

コレクションからデータを見つけて取得する際に問題があります。ここに私の収集データ MongoDB動的フィールドから検索するクエリ

/* 1 */ 
{ 
    "_id" : 1, 
    "name" : "sue", 
    "age" : 19, 
    "type" : 1, 
    "points" : { 
     "A" : { 
      "type" : "label", 
      "values" : "abc" 
     }, 
     "B" : { 
      "mandatory" : false, 
      "type" : "text" 
     }, 
     "C" : { 
      "mandatory" : false, 
      "type" : "text" 
     } 
    } 
} 

/* 2 */ 
{ 
    "_id" : 2, 
    "name" : "bob", 
    "age" : 42, 
    "type" : 1, 
    "points" : { 
     "B" : { 
      "type" : "label", 
      "values" : "" 
     }, 
     "C" : { 
      "mandatory" : false, 
      "type" : "text" 
     } 
    } 
} 

/* 3 */ 
{ 
    "_id" : 3, 
    "name" : "ahn", 
    "age" : 22, 
    "type" : 2, 
    "points" : { 
     "A" : { 
      "type" : "label", 
      "values" : "abc" 
     }, 
     "C" : { 
      "mandatory" : false, 
      "type" : "text" 
     } 
    } 
} 

/* 4 */ 
{ 
    "_id" : 4, 
    "name" : "xi", 
    "age" : 34, 
    "type" : 2, 
    "points" : { 
     "A" : { 
      "type" : "label", 
      "allowedValues" : "abc" 
     }, 
     "C" : { 
      "mandatory" : false, 
      "type" : "text" 
     } 
    } 
} 

/* 5 */ 
{ 
    "_id" : 5, 
    "name" : "xyz", 
    "age" : 23, 
    "type" : 2, 
    "points" : { 
     "B" : { 
      "mandatory" : false, 
      "type" : "text" 
     }, 
     "C" : { 
      "values" : "C", 
      "type" : "text" 
     } 
    } 
} 

/* 6 */ 
{ 
    "_id" : 6, 
    "name" : "abc", 
    "age" : 43, 
    "type" : 1, 
    "points" : { 
     "A" : { 
      "type" : "label", 
      "values" : "abc" 
     }, 
     "B" : { 
      "mandatory" : false, 
      "type" : "text" 
     } 
    } 
} 

私はフィールド "points"から "type"="label""values"=""を持っているすべての文書をしたいです。

find()mongoDBに入力するとどうすればいいですか?誰もがこれについてアイデアを持っていますか?

+0

A、B、またはCは事前に知っていますか? – chridam

+0

いいえ、それは修正されていません。もっとたくさんあるかもしれません。動的なフィールドが追加されます。 – Meteor

+0

@chridamでも、私はmongoDBに新規参加しています。だから私が直接適用できる解決策があれば素晴らしいだろう。 – Meteor

答えて

0

現在の設計と同じように、あなたは、最終的なクエリの上に適用された場合$orクエリを作成するために、このリストを解析し、回収などvar dynamic_keys = ["A", "B", "C"]内のすべての動的なキーのリストを取得する仕組みが必要になります基本的に動的なキーのリストを取得する最初の操作は、地図-削減を通じてのみ可能です

db.collection.find({ 
    "$or": [ 
     { "points.A.type": "label", "points.A.values": "" }, 
     { "points.B.type": "label", "points.B.values": "" }, 
     { "points.C.type": "label", "points.C.values": "" } 
    ] 
}) 

のようになります。

のmongoシェルで、次のMapReduceの操作を実行すると、_id値としてすべての動的キーでtemp_collection_keysと呼ばれる別の一時コレクション移入します:

mr = db.runCommand({ 
    "mapreduce": "collection", 
    "map": function() { 
     for (var key in this.points) { emit(key, null); } 
    }, 
    "reduce": function() { }, 
    "out": "temp_collection_keys" 
}) 

は、すべての動的キーのリストを取得するには、上の個別実行を結果のコレクション:

db[mr.result].distinct("_id") 
["A", "B", "C"] 

は今、あなたはOBJECを作成してクエリを組み立てることができ、上記のリストを与えられましたそのプロパティはループ内で設定されます。通常、あなたの$or文書では、このような構造を持っています:だからサブドキュメントキーの上のリストを使用して

var orQuery = { 
    "$or": [ 
     { "points.A.type": "label", "points.A.values": "" }, 
     { "points.B.type": "label", "points.B.values": "" }, 
     { "points.C.type": "label", "points.C.values": "" } 
    ] 
}; 

、あなたは動的に明確な配列の結果に適用されるネイティブのJavaScriptのmap()方法を用いて、上記の$や配列を構築することができます。

var mr = db.runCommand({ 
    "mapreduce": "collection", 
    "map": function() { 
     for (var key in this.points) { emit(key, null); } 
    }, 
    "reduce": function() { }, 
    "out": "temp_collection_keys" 
}); 

var orArray = db[mr.result].distinct("_id").map(function (key){ 
    var obj = { }; 
    obj["points."+key+".type"] = "label"; 
    obj["points."+key+".values"] = ""; 
    return obj; 
}); 

db.collection.find({ "$or": orArray }); 

サンプル出力

{ 
    "_id" : 2, 
    "name" : "bob", 
    "age" : 42, 
    "type" : 1, 
    "points" : { 
     "B" : { 
      "type" : "label", 
      "values" : "" 
     }, 
     "C" : { 
      "mandatory" : false, 
      "type" : "text" 
     } 
    } 
} 
関連する問題