2016-06-21 68 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" 
     } 
    } 
} 

我想這有"type"="label""values"=""從外地"points"的所有文件。

如何使用find()mongoDB中實現此列表?有沒有人有這個想法?

+0

您知道A,B或C是事先知道嗎? – chridam

+0

不,這不是修復..可能還有更多。它的動態字段將被添加。 – Meteor

+0

@chridam但暗示,但我是新的在mongoDB。所以,如果你有任何我可以直接申請的解決方案,那將是非常好的。 – Meteor

回答

0

與目前的設計,您將需要一個機制來獲取在收集如var dynamic_keys = ["A", "B", "C"]所有動態密鑰的列表,解析此列表創建$or查詢,而如果應用到您的最終查詢以上基本上應該看起來像

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": "" } 
    ] 
}) 

獲取動態密鑰列表的第一個操作是唯一可能通過的map-reduce。

運行在蒙戈外殼下面精簡操作將填充一個單獨的臨時集合稱爲temp_collection_keys所有動態密鑰作爲_id值:

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組合查詢t將其屬性設置在一個循環中。通常情況下你$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" 
     } 
    } 
}