【问题标题】:MongoDB Group on Multiple Levels多层次的 MongoDB 组
【发布时间】:2023-03-23 23:11:01
【问题描述】:

我有一组事件数据,我想对其执行聚合/分组以将事件数据汇总为单个结果。我遇到的问题只是想知道如何以我想要返回结果的方式组织数据。

样本数据:

db.events.find({})

{
    eventId : "abc",
    eventDate : 1420088400000,
    eventLength : 1800000,
    eventStart : 59100000,
    attendees : [
        "userA",
        "userB",
        "userC"
    ],
    otherData : "...",
    etc : "..."
},{
    eventId : "def",
    eventDate : 1421557200000,
    eventLength : 3600000,
    eventStart : 36000000,
    attendees : [
        "userA",
        "userG",
        "userZ"
    ],
    otherData : "...",
    etc : "..."
},{
    eventId : "ghi",
    eventDate : 1420088400000,
    eventLength : 7200000,
    eventStart : 45000000,
    attendees : [
        "userD",
        "userE",
        "userA"
    ],
    otherData : "...",
    etc : "..."
}

基本上,日期/时间/和长度都存储为表示毫秒的 long 或 int,因此添加 eventDate + eventStart 将为您提供 UTC 中的日期和开始时间。添加 eventDate + eventStart + eventLength 将为您提供 UTC 中的事件结束时间。

我要做的是创建和聚合,允许我在与会者中 $match 上的 userId(这里没有问题),但按天/周/月/年/整体显示一组数据。

因此示例结果将是例如(这与上面示例数据中的时间不准确,但正在寻找如何编写此分组的脚本..)

{
    userId : "userA",
    req : 75.0,
    totals : [
        {
            period : "day",
            events : 2,              //this means two event for today
            eventsLength : 7200000,  //$sum of the 2 events length
        },{
            period : "week",
            events : 3,              //this means 3 events in the week
            eventsLength : 9600000,  //$sum of the 3 events length
        },{
            period : "month",
            events : 8,              //this means 8 events in the month
            eventsLength : 15000000, //$sum of the 8 events length
        },{
            period : "year",
            events : 15,             //this means 15 events in the year
            eventsLength : 15000000, //$sum of the 15 events length
        },{
            period : "overall",
            events : 23,             //this means 23 events lifetime
            eventsLength : 72000000, //$sum of the 23 events length
        }
    ]
}

因此,对于每个“期间”,我基本上想保持一个运行总计并 $sum 总结 eventLength 和事件数量。 “req”表示给定当前日期,用户已完成 3/4 个事件 (75%)。它与总数无关,基本上它只是一个百分比,说目标是每周 4 次活动,这是你完成的百分比。所以你在“周”期间看到,他们只有四分之三作为目标。

在我的聚合中,我尝试了 $match、$project 和 $group 的组合来尝试生成此输出,但我希望有人可以帮助进行分组以获得运行总计..​​

在给定当前日期的情况下,我已经计算出每个时期的日期/毫秒数,所以我已经将其预先确定为变量,我只是不知道如何构建聚合/分组来产生这个结果..

感谢任何帮助!

【问题讨论】:

  • 您的问题构建中的小问题(建设性批评)。您考虑的结果数据结构对任何语言都无效,但我们假设 JSON,因此无效。也许您的意思是每个分组的数组。关于问题本身的更多信息,您可以在多个深度上执行此操作,但在单个语句中可能不太实用。这里的另一个未知数是“req”。你怎么知道基于数据模型提供的3/4?它适用于哪个指标? “周”、“日”、“年”?这一切都提出了一个更清晰的问题。但也要考虑这些陈述。
  • 嗨,尼尔,是的,它是一个数组,而不是一组句点。我希望每个数组元素都可以运行一个组,如果我有 5 个组语句要添加的话数据的每个元素到总计数组.. 这样它会显示为“运行总计”但是它将 5 个结果添加到结果数据集中..
  • “req”或要求,将基于当前日期所在的周,M->Sun (ISO)。
  • 这里还有可用作语句变量的内容,首先在字符串中构建,替换变量,然后运行..
  • Daystart:1421643600000 Daystart:1421643600000周末:1422248399999月

标签: mongodb mapreduce mongodb-query aggregation-framework


【解决方案1】:

在昨天搞砸了这个问题之后,我有了这个解决方案,这不是我正在寻找的确切输出,其中我将总计作为数组,每个“句点”或数组元素作为汇总总计的集合,但是这会输出一个集合,按“期间(日/周/月/年/总体)”分段,每个集合都有累计总数..

{
    $match: {userId : "ABC123"}
},{
    $project : {
    _id : 0,
    d : {$cond:{if:{$and:[{$gte:["$eventDate", "${dayStart}"]},{$lte:["$eventDate", "${dayEnd}"]}]}, 
        then: {d : "$eventLength", c : {"$literal" : 1}}, 
        else: null }
    },
    w : {$cond:{if:{$and:[{$gte:["$eventDate","${weekStart}"]},{$lte:["$eventDate", "${weekEnd}"]}]}, 
        then: {d : "$eventLength", c : {"$literal" : 1}}, 
        else: null }
    },
    m : {$cond:{if:{$and:[{$gte:["$eventDate","${monthStart}"]},{$lte:["$eventDate","${monthEnd}"]}]}, 
        then: {d : "$eventLength", c : {"$literal" : 1}}, 
        else: null }
    },
    y : {$cond:{if:{$and:[{$gte:["$eventDate","${yearStart}"]},{$lte:["$eventDate","${yearEnd}"]}]}, 
        then: {d : "$eventLength", c : {"$literal" : 1}}, 
        else: null }
    },
    o : {$cond:{if:{$lte:["$eventDate","${yearEnd}"]}, 
        then: {d : "$eventLength", c : {"$literal" : 1}}, 
        else: null }
    }
}
},{
$group : {
    _id : null,
    day_d : {$sum : "$d.d"},
    day_c : {$sum : "$d.c"},
    week_d : {$sum : "$w.d"},
    week_c : {$sum : "$w.c"},
    month_d : {$sum : "$m.d"},
    month_c : {$sum : "$m.c"},
    year_d : {$sum : "$y.d"},
    year_c : {$sum : "$y.c"},
    over_d : {$sum : "$o.d"},
    over_c : {$sum : "$o.c"}
} 
},{
$project : {
    _id : 0,
    day : {events : "$day_c", millisTotal : "$day_d"},
    week : {events : "$week_c", millisTotal : "$week_d"},
    month : {events : "$month_c", millisTotal : "$month_d"},
    year : {events : "$year_c", millisTotal : "$year_d"},
    overall : {events : "$over_c", millisTotal : "$over_d"},
    req : {
        $cond : { 
            if : { $gte : ["$week_c", 4]}, then : 100, 
            else : {
                $cond : {
                    if : { $eq : ["$week_c", 3] }, then : 75,
                    else : {
                        $cond : {
                            if : { $eq : ["$week_c", 2] }, then : 50,
                            else : {
                                $cond : {
                                    if : { $eq : ["$week_c", 1] }, then : 25,
                                    else : 0
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
} 

这会生成一个如下所示的输出..

{
day : {
    events : 1,
    millisTotal : 7200000
},
week : {
    events : 2,
    millisTotal : 14400000
},
month : {
    events : 17,
    millisTotal : 87345000
},
year : {
    events : 17,
    millisTotal : 87345000
},
overall : {
    events : 18,
    millisTotal : 92745000
},
req : 50
}

我注意到的一件事是几乎不可能将 $project 返回到数组元素中,这样我就可以将每个周期集合作为数组元素的“totals : []”,但是现在这可行.. 如果有人有反馈或更好的方法来实现这一点,我会暂时打开它,看看是否有更好的答案。我喜欢这个作为总计数组的原因是使用这个输出的逻辑可以更加动态,不要期望一组特定的“键”作为日/周/月/年/整体。

【讨论】:

    猜你喜欢
    • 2018-05-14
    • 2021-06-18
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    相关资源
    最近更新 更多