Rails&Mongoid独特的结果

考虑下面的mongo集合示例:

{"_id" : ObjectId("4f304818884672067f000001"), "hash" : {"call_id" : "1234"}, "something" : "AAA"} {"_id" : ObjectId("4f304818884672067f000002"), "hash" : {"call_id" : "1234"}, "something" : "BBB"} {"_id" : ObjectId("4f304818884672067f000003"), "hash" : {"call_id" : "1234"}, "something" : "CCC"} {"_id" : ObjectId("4f304818884672067f000004"), "hash" : {"call_id" : "5555"}, "something" : "DDD"} {"_id" : ObjectId("4f304818884672067f000005"), "hash" : {"call_id" : "5555"}, "something" : "CCC"} 

我想查询这个集合,只得到每个“call_id”的第一个条目,换句话说,我试图获得基于“call_id”的唯一结果。 我尝试使用.distinct方法:

 @result = Myobject.all.distinct('hash.call_id') 

但结果数组将只包含唯一的call_id字段:

 ["1234", "5555"] 

我也需要所有其他领域。 是否可以像这样进行查询?:

 @result = Myobject.where('hash.call_id' => Myobject.all.distinct('hash.call_id')) 

谢谢

您不能简单地使用distinct返回文档(或子集)。 根据文档 ,它只返回基于给定键的不同值数组。 但是你可以通过使用map-reduce来实现这一点

 var _map = function () { emit(this.hash.call_id, {doc:this}); } var _reduce = function (key, values) { var ret = {doc:[]}; var doc = {}; values.forEach(function (value) { if (!doc[value.doc.hash.call_id]) { ret.doc.push(value.doc); doc[value.doc.hash.call_id] = true; //make the doc seen, so it will be picked only once } }); return ret; } 

上面的代码是自解释的,在map函数上我通过键hash.call_id对它进行分组并返回整个doc,因此可以通过reduce hash.call_id进行处理。

在reduce函数上,只需遍历分组结果集,并从分组集中选择一个项目(在多个重复键值中 – 不同的模拟)。

最后创建一些测试数据

 > db.disTest.insert({hash:{call_id:"1234"},something:"AAA"}) > db.disTest.insert({hash:{call_id:"1234"},something:"BBB"}) > db.disTest.insert({hash:{call_id:"1234"},something:"CCC"}) > db.disTest.insert({hash:{call_id:"5555"},something:"DDD"}) > db.disTest.insert({hash:{call_id:"5555"},something:"EEE"}) > db.disTest.find() { "_id" : ObjectId("4f30a27c4d203c27d8f4c584"), "hash" : { "call_id" : "1234" }, "something" : "AAA" } { "_id" : ObjectId("4f30a2844d203c27d8f4c585"), "hash" : { "call_id" : "1234" }, "something" : "BBB" } { "_id" : ObjectId("4f30a2894d203c27d8f4c586"), "hash" : { "call_id" : "1234" }, "something" : "CCC" } { "_id" : ObjectId("4f30a2944d203c27d8f4c587"), "hash" : { "call_id" : "5555" }, "something" : "DDD" } { "_id" : ObjectId("4f30a2994d203c27d8f4c588"), "hash" : { "call_id" : "5555" }, "something" : "EEE" } 

并运行此地图减少

 > db.disTest.mapReduce(_map,_reduce, {out: { inline : 1}}) { "results" : [ { "_id" : "1234", "value" : { "doc" : [ { "_id" : ObjectId("4f30a27c4d203c27d8f4c584"), "hash" : { "call_id" : "1234" }, "something" : "AAA" } ] } }, { "_id" : "5555", "value" : { "doc" : [ { "_id" : ObjectId("4f30a2944d203c27d8f4c587"), "hash" : { "call_id" : "5555" }, "something" : "DDD" } ] } } ], "timeMillis" : 2, "counts" : { "input" : 5, "emit" : 5, "reduce" : 2, "output" : 2 }, "ok" : 1, } 

您将获得不同集的第一个文档。 您可以通过首先对map / reduce函数进行字符串化并像这样调用mapreduce来在mongoid中执行相同的操作

  MyObject.collection.mapreduce(_map,_reduce,{:out => {:inline => 1},:raw=>true }) 

希望能帮助到你

Interesting Posts