ruby-on-rails - Rails & Mongoid 独特的结果

标签 ruby-on-rails mongodb distinct database

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

谢谢

最佳答案

您不能简单地使用不同的返回文档(或子集)。根据 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" }

并运行这个 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,
}

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

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

希望对你有帮助

关于ruby-on-rails - Rails & Mongoid 独特的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9169364/

相关文章:

jquery - JSON问题中的Rails HTML编码

ruby-on-rails - 在 Rails App 中使用 secret 密码

ruby-on-rails - Active Record 对象重新加载和重新加载!?

mongodb - 使用mongodb go驱动程序将用户添加到mongodb

php - 如何正确使用 DISTINCT 为每个 user_id 仅显示一项

SQL 从多个表中选择不同的值

ruby-on-rails - rails 邮箱未定义方法 `mailboxer_email'

javascript - 如何在 mongodb 中上传文件(不需要使用 BSON 的 gridfs )

mongodb - 使用 mongodb-source-connect 时出现 "The $changeStream stage is only supported on replica sets"错误

mysql - 从存储过程输出 JOINS 的不同值