Rails& Mongoid独有的结果 [英] Rails & Mongoid unique results

查看:251
本文介绍了Rails& Mongoid独有的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下mongo集合的示例:

Consider the following example of mongo collection:

{"_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方法:

I would like to query this collection and get only the first entry for each "call_id", in other words i'm trying to get unique results based on "call_id". I tried to use .distinct method:

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

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

but the resulting array will contain only the unique call_id fields:

["1234", "5555"]


$ b b

我需要所有其他字段。
可以像这样进行查询:

and I need all the other fields too. Is it possible to make a query like this one?:

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

p>

推荐答案

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

You cannot simply return the document(or subset) by using the distinct. As per the documentation it only returns the distinct array of values based on the given key. But you can achieve this by using 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 并返回整个文档,以便可以通过reduce函数处理。

The above code is self explanatory, on map function i am grouping it by key hash.call_id and returning the whole doc so it can be processed by reduce funcition.

循环通过分组结果集,并从分组集中选择一个项目(在多个重复键值之间 - 不同的模拟)。

On reduce function, just loop through the grouped result set and pick only one item from the grouped set (among the multiple duplicate key values - distinct simulation).

最后创建一些测试数据

> 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" }

并运行此地图reduce

and running this map reduce

> 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,
}

您得到不同集合的第一个文档。你可以做同样的mongoid通过首先stringify map / reduce函数和调用mapreduce像这样

You get the first document of the distinct set. You can do the same in mongoid by first stringify the map/reduce functions and call mapreduce like this

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


b $ b

希望它有助于

Hope it helps

这篇关于Rails& Mongoid独有的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆