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