ruby-on-rails – Rails和Mongoid独特的结果

考虑下面的mongo集合示例:
{"_id" : ObjectId("4f304818884672067f000001"),"hash" : {"call_id" : "1234"},"something" : "AAA"}
{"_id" : ObjectId("4f304818884672067f000002"),"something" : "BBB"}
{"_id" : ObjectId("4f304818884672067f000003"),"something" : "CCC"}
{"_id" : ObjectId("4f304818884672067f000004"),"hash" : {"call_id" : "5555"},"something" : "DDD"}
{"_id" : ObjectId("4f304818884672067f000005"),"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返回文档(或子集).根据 documentation,它只返回基于给定键的不同值数组.但是你可以通过使用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 funcition进行处理.

在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"),"something" : "BBB" }
{ "_id" : ObjectId("4f30a2894d203c27d8f4c586"),"something" : "CCC" }
{ "_id" : ObjectId("4f30a2944d203c27d8f4c587"),"hash" : { "call_id" : "5555" },"something" : "DDD" }
{ "_id" : ObjectId("4f30a2994d203c27d8f4c588"),"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,{:out => {:inline => 1},:raw=>true })

希望能帮助到你

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...