Mongodb Mongo和Pivot

Mongodb Mongo和Pivot,mongodb,pivot,Mongodb,Pivot,在这个问题上我需要mongo的帮助:我有集合统计信息(UserId、EventId、Count、Date) 收集的是数据 用户ID |事件ID |计数|日期 我需要这个结果 用户ID |计数(事件)1 |计数(事件)ID(2) 在Mongo没有地图还原的情况下是否可能? 谢谢你的帮助 您必须通过操作来完成此操作 您的映射函数如下所示:(未经测试!): 这将发出一系列由UserId和一个对象组成的对,该对象具有一个名称不同的属性,该属性的值为count 然后,reduce函数会将结果合并为一个(未

在这个问题上我需要mongo的帮助:我有集合统计信息(UserId、EventId、Count、Date) 收集的是数据

用户ID |事件ID |计数|日期 我需要这个结果

用户ID |计数(事件)1 |计数(事件)ID(2) 在Mongo没有地图还原的情况下是否可能?
谢谢你的帮助

您必须通过操作来完成此操作

您的映射函数如下所示:(未经测试!):

这将发出一系列由UserId和一个对象组成的对,该对象具有一个名称不同的属性,该属性的值为count

然后,reduce函数会将结果合并为一个(未经测试-我不确定是否可以增加一个不存在的属性,我现在无法测试):


out:{inline:1}
将结果输出到控制台。通常使用MapReduce创建一个包含结果的新集合。有关更多信息,请参阅。

使用
聚合()执行此项工作更容易、更快。

我们将使用
$project
为每个事件创建一个计数器字段,从文档中填入计数,如果事件匹配,则为零。然后,我们将按用户id对所有事件计数器进行汇总

为了便于解释,首先让我展示一下,对于您的示例中的两个不同事件(1和2),这看起来像是硬编码的:

db.xx.aggregate([
    { $project: { userid:1,
                  cnt_e1: { $cond: [ { $eq: [ "$event", 1 ] }, "$count", 0 ] },
                  cnt_e2: { $cond: [ { $eq: [ "$event", 2 ] }, "$count", 0 ] },
    } },
    { $group: { _id: "$userid", cnt_e1: { $sum: "$cnt_e1" }, cnt_e2: { $sum: "$cnt_e2" } } },  
    { $sort: { _id: 1 } },
])
对于给定集合:

> db.xx.find({},{_id:0})
{ "userid" : 1, "event" : 1, "count" : 10 }
{ "userid" : 1, "event" : 1, "count" : 15 }
{ "userid" : 1, "event" : 2, "count" : 12 }
{ "userid" : 2, "event" : 1, "count" : 5 }
{ "userid" : 3, "event" : 2, "count" : 10 }
结果是:

{
    "result" : [
        {
            "_id" : 1,
            "cnt_e1" : 25,
            "cnt_e2" : 12
        },
        {
            "_id" : 2,
            "cnt_e1" : 5,
            "cnt_e2" : 0
        },
        {
            "_id" : 3,
            "cnt_e1" : 0,
            "cnt_e2" : 10
        }
    ],
    "ok" : 1
}
要对可变事件执行此操作,我们必须生成投影和分组。我们将使用
distinct()
命令获得所有可能事件的数组(您可能希望在“事件”上定义索引)。然后,通过在数组上循环,将这两条语句创建为JSON对象:

project = {};
project.$project = {};
project.$project.userid = 1;

group = {};
group.$group = {};
group.$group._id = '$userid'

events = db.xx.distinct( "event" );
events.forEach( function( e ) {
    field = "cnt_e" + e;

    eval("project.$project." + field + " = {}");
    eval("project.$project." + field + ".$cond = []");
    eval("project.$project." + field + ".$cond[0] = {}");
    eval("project.$project." + field + ".$cond[0].$eq = []");
    eval("project.$project." + field + ".$cond[0].$eq[0] = '$event'");
    eval("project.$project." + field + ".$cond[0].$eq[1] = " + e );
    eval("project.$project." + field + ".$cond[1] = '$count'");
    eval("project.$project." + field + ".$cond[2] = 0");

    eval("group.$group." + field + " = {}");
    eval("group.$group." + field + ".$sum = '$" + field + "'");
});

//printjson(project);
//printjson(group);

db.xx.aggregate([
    project,
    group,
    { $sort: { _id: 1 } },
])
结果与上述相同

注:以上适用于数字事件。如果它们是字符串,则必须调整生成器

乍一看,这可能比@Philipp的mapReduce更复杂。但这不会返回每个用户的所有事件,只返回那些有计数的事件。对于完整的垂直到水平映射,您还必须生成映射和reduce函数


有关aggregate()的更多信息,请参见

谢谢,不幸的是,我有“另一个”Map Reduce变体。但是我需要这个不带Map reduce的查询。例如:按聚合或$group或$project。。。。你知道一些相关的东西吗?为什么你需要在没有MapReduce的情况下做它?这不是“我不能使用MapReduce”的条件。我是Mongo的begginer,我正在寻找解决这个问题的最佳方法。简单的方法是使用MapReduce,另一种方法是:我可以使用新的集合,通过过滤器EventId将数据导入到这个集合中,并返回一个返回值(如SQLUnion),但我认为有更好的方法来实现。也许这种方式是错误的?@Philipp,你不确定的那行应该是这样的
isNaN(ret[k])?ret[k]=值[k]:ret[k]+=值[k] db.yourCollection.mapReduce(
                 mapFunction,
                 reduceFunction,
                 out: { inline: 1 }
               )
db.xx.aggregate([
    { $project: { userid:1,
                  cnt_e1: { $cond: [ { $eq: [ "$event", 1 ] }, "$count", 0 ] },
                  cnt_e2: { $cond: [ { $eq: [ "$event", 2 ] }, "$count", 0 ] },
    } },
    { $group: { _id: "$userid", cnt_e1: { $sum: "$cnt_e1" }, cnt_e2: { $sum: "$cnt_e2" } } },  
    { $sort: { _id: 1 } },
])
> db.xx.find({},{_id:0})
{ "userid" : 1, "event" : 1, "count" : 10 }
{ "userid" : 1, "event" : 1, "count" : 15 }
{ "userid" : 1, "event" : 2, "count" : 12 }
{ "userid" : 2, "event" : 1, "count" : 5 }
{ "userid" : 3, "event" : 2, "count" : 10 }
{
    "result" : [
        {
            "_id" : 1,
            "cnt_e1" : 25,
            "cnt_e2" : 12
        },
        {
            "_id" : 2,
            "cnt_e1" : 5,
            "cnt_e2" : 0
        },
        {
            "_id" : 3,
            "cnt_e1" : 0,
            "cnt_e2" : 10
        }
    ],
    "ok" : 1
}
project = {};
project.$project = {};
project.$project.userid = 1;

group = {};
group.$group = {};
group.$group._id = '$userid'

events = db.xx.distinct( "event" );
events.forEach( function( e ) {
    field = "cnt_e" + e;

    eval("project.$project." + field + " = {}");
    eval("project.$project." + field + ".$cond = []");
    eval("project.$project." + field + ".$cond[0] = {}");
    eval("project.$project." + field + ".$cond[0].$eq = []");
    eval("project.$project." + field + ".$cond[0].$eq[0] = '$event'");
    eval("project.$project." + field + ".$cond[0].$eq[1] = " + e );
    eval("project.$project." + field + ".$cond[1] = '$count'");
    eval("project.$project." + field + ".$cond[2] = 0");

    eval("group.$group." + field + " = {}");
    eval("group.$group." + field + ".$sum = '$" + field + "'");
});

//printjson(project);
//printjson(group);

db.xx.aggregate([
    project,
    group,
    { $sort: { _id: 1 } },
])