【问题标题】:Rails & Mongoid unique resultsRails 和 Mongoid 独特的结果
【发布时间】:2012-02-07 00:22:00
【问题描述】:

考虑以下 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'))

谢谢

【问题讨论】:

    标签: ruby-on-rails mongodb distinct database


    【解决方案1】:

    您不能简单地使用 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 对它进行分组并返回整个文档,以便它可以被 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" }
    

    并运行此地图减少

    > 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 中执行相同操作,首先将 map/reduce 函数字符串化并像这样调用 mapreduce

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

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多