我有一个包含日期的架构的集合。我想对查询的结果进行整形,以便按年份和月份进行分组,但不进行汇总,只进行排序。
所以我的模型看起来像这样:
var RoundSchema = new Schema({
user: {type: Schema.Types.ObjectId, ref: 'User', required: '{PATH} is required!'},
course: {type: Schema.Types.ObjectId, ref: 'Course', required: '{PATH} is required!'},
date: {type: Date, required: '{PATH} is required!'},
score: Number
});
变形如下:
[
{
"year": 2014,
"month": "April",
"rounds": [
{
"user": "5334d6650685f68c22aa460b",
"date": "2014-04-23T05:00:00.000Z",
"course": "5340ab6000806e2433864cfc",
"score": 73,
"_id": "534f102667d635381834367b"
},
{
"user": "5334d6650685f68c22aa460b",
"date": "2014-04-21T05:00:00.000Z",
"course": "5340ab6000806e2433864cfc",
"score": 75,
"_id": "534f100067d6353818343671"
}
]
},
{
"year": 2014,
"month": "May",
"rounds": [
{
"user": "5334d6650685f68c22aa460b",
"date": "2014-05-05T05:00:00.000Z",
"course": "5337611d8d03819024515cf9",
"score": 81,
"_id": "534dc38780f1a854236203f3"
},
{
"user": "5334d6650685f68c22aa460b",
"date": "2014-05-04T05:00:00.000Z",
"course": "5337611d8d03819024515cf9",
"score": 77,
"_id": "534dc22c80f1a854236203e9"
}
]
}
]
我猜我可以在MongoDB中使用map-reduce或聚合管道,但我无法理解语法。现在感觉像保龄球一样锋利。
任何人都有想法让我开始?
答案 0 :(得分:1)
这可以使用聚合框架非常简单地完成。这不仅仅是为了总结"价值观,但也擅长文件重塑。
这是你最好的选择,好像"非聚合"使用mapReduce代码看起来有点简单,因为该进程依赖于JavaScript解释器,而不是聚合框架的本机代码,因此mapReduce运行速度会慢得多。大数据相当可观。
db.collection.aggregate([
// Place all items in an array by year and month
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
},
"rounds": { "$push": {
"user": "$user",
"date": "$date",
"course": "$course",
"score": "$score",
"_id": "$_id"
}}
}},
// Sort the results by year and month
{ "$sort": { "_id.year": 1, "_id.date": 1 } },
// Optional project to your exact form
{ "$project": {
"_id": 0,
"year": "$_id.year",
"month": "$_id.month",
"rounds": 1
}}
])
或者可能没有您指定的数组,并将所有内容保留为平面形式:
db.collection.aggregate([
{ "$project": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"user": 1,
"date": 1,
"course": 1,
"score": 1
}},
{ "$sort": { "year": 1, "month": 1 } }
])
甚至可以确切地指定您使用月份名称的方式:
db.collection.aggregate([
// Place all items in an array by year and month
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
},
"rounds": { "$push": {
"user": "$user",
"date": "$date",
"course": "$course",
"score": "$score",
"_id": "$_id"
}}
}},
// Sort the results by year and month
{ "$sort": { "_id.year": 1, "_id.date": 1 } },
// Optionally project to your exact form
{ "$project": {
"_id": 0,
"year": "$_id.year",
"month": { "$cond": [
{ "$eq": [ "$_id.month": 1 ] },
"January",
{ "$cond": [
{ "$eq": [ "$_id.month": 2 ] },
"February",
{ "$cond": [
{ "$eq": [ "$_id.month": 3 ] },
"March",
{ "$cond": [
{ "$eq": [ "$_id.month": 4 ] },
"April",
{ "$cond": [
{ "$eq": [ "$_id.month": 5 ] },
"May",
{ "$cond": [
{ "$eq": [ "$_id.month": 6 ] },
"June",
{ "$cond": [
{ "$eq": [ "$_id.month": 7 ] },
"July",
{ "$cond": [
{ "$eq": [ "$_id.month": 8 ] },
"August",
{ "$cond": [
{ "$eq": [ "$_id.month": 9 ] },
"September",
{ "$cond": [
{ "$eq": [ "$_id.month": 10 ] },
"October",
{ "$cond": [
{ "$eq": [ "$_id.month": 11 ] },
"November",
"December"
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]},
"rounds": 1
}}
])
当然,这是过度的,只是为了表明它可以完成。
当然有Operator reference所以你可以理解所用运算符的用法。您可能希望通过添加自己的 $match
条件来更改此限制,以限制您正在查看的日期范围。或者实际上用于其他目的。