Daw*_*wid 3 database ruby-on-rails distinct mongodb
考虑下面的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"}
Run Code Online (Sandbox Code Playgroud)
我想查询这个集合,只得到每个"call_id"的第一个条目,换句话说,我试图获得基于"call_id"的唯一结果.我尝试使用.distinct方法:
@result = Myobject.all.distinct('hash.call_id')
Run Code Online (Sandbox Code Playgroud)
但结果数组将只包含唯一的call_id字段:
["1234", "5555"]
Run Code Online (Sandbox Code Playgroud)
我也需要所有其他领域.是否可以像这样进行查询?:
@result = Myobject.where('hash.call_id' => Myobject.all.distinct('hash.call_id'))
Run Code Online (Sandbox Code Playgroud)
谢谢
您不能简单地使用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;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码是自解释的,在map函数上我按键对它进行分组hash.call_id
并返回整个doc,因此可以通过reduce函数进行处理.
在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" }
Run Code Online (Sandbox Code Playgroud)
并运行此地图减少
> 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,
}
Run Code Online (Sandbox Code Playgroud)
您将获得不同集的第一个文档.您可以通过首先对map/reduce函数进行字符串化并像这样调用mapreduce来在mongoid中执行相同的操作
MyObject.collection.mapreduce(_map,_reduce,{:out => {:inline => 1},:raw=>true })
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你
归档时间: |
|
查看次数: |
3203 次 |
最近记录: |