【发布时间】:2015-10-19 20:20:06
【问题描述】:
我需要获取 MongoDB 中所有记录的周范围列表。当我单击一周范围时,它将仅显示该周范围的记录。点击周范围会发送周的 ID(比如说42,即 2015 年的第 42 周),它应该会得到这些结果。
问题:如何查询给定周数和年份的一组记录?这应该可行,对吧?
架构:
var orderSchema = mongoose.Schema({
date: Date, //ISO date
request: {
headers : {
...
首先:获取所有对象的所有周 ID:
var query = Order.aggregate(
[
{
$project:
{
week:
{
$week: '$date'
}
}
},
{
$group:
{
_id: null,
distinctDate:
{
$addToSet:
{
week: '$week'
}
}
}
}
]
);
结果:
distinctDate: Array[35]
0: Object
week: 40
1: Object
week: 37
...
使用MomentJS 转换为周范围并显示:
data.forEach(function(v, k) {
$scope.weekRanges.push(getWeekRange(v.week));
});
function getWeekRange(weekNum) {
var monday = moment().day("Monday").isoWeek(weekNum).format('MM-DD-YYYY');
var sunday = moment().day("Sunday").isoWeek(weekNum).format('MM-DD-YYYY');
...
输出:
Week
10-12-2015 to 10-18-2015 //week ID 42
10-05-2015 to 10-11-2015 //week ID 41
09-28-2015 to 10-04-2015 ...
...
第二次:点击周范围,获取 Objects Per Week ID:
var year = 2015;
var weekID = weekParamID; //42
if (!Order) {
Order = mongoose.model('Order', orderSchema());
}
var query = Order.aggregate(
{
$project:
{
cust_ID : '$request.headers.custID',
cost : '$response.body.pricing.cost',
year :
{
$year: '$date'
},
month :
{
$month: '$date'
},
week:
{
$week: '$date'
},
day:
{
$dayOfMonth: '$date'
}
}
},
{
$match:
{
year : year, //2015
week : weekID //42
}
}
);
如果我点击周范围10-12-2015 to 10-18-2015(第 42 周),我会得到日期超出范围(2015 年 10 月 19 日)的结果:
10-19-2015 Order info
10-18-2015 Order info
10-19-2015 Order info
使用 MongoDB 命令行:
db.mycollection.aggregate({ $project: { week: { $week: '$date' }, day: { $dayOfMonth: '$date' } } }, { $match: { week: 42 } }
结果:
{ "_id" : "1bd482f6759b", "week" : 42, "day" : 19 } //shouldn't exceed week range
{ "_id" : "b3d38759", "week" : 42, "day" : 19 }
编辑:更新
因此,MongoDB ISO 周(从周日开始)和 Moment JS ISO(从周一开始)存在差异。
This SO post 建议从查询中减去日期,以便 Mongo 日期从星期一开始:
{
$project:
{
week: { $week: [ "$datetime" ] },
dayOfWeek:{$dayOfWeek:["$datetime"]}}
},
{
$project:
{
week:{$cond:[{$eq:["$dayOfWeek",1]},{$subtract:["$week",1]},'$week']}
}
}
我用我的查询实现了这个,但现在它没有返回我需要的两个字段:
cust_ID : '$request.headers.custID',
cost : '$response.body.pricing.cost'
查询:
db.mycollection.aggregate(
{
$project:
{
cust_ID : '$request.headers.custID',
cost : '$response.body.pricing.cost',
week:
{
$week: ['$date']
},
dayOfWeek:
{
$dayOfWeek: ['$date']
}
}
},
{
$project:
{
week: {
$cond: [
{
$eq: [
"$dayOfWeek", 1
]
},
{
$subtract: [
"$week", 1
]
}, '$week'
]
}
}
},
{
$match:
{
week : 42
}
}
);
结果:
{ "_id" : "387e2", "week" : 42 }
{ "_id" : "ef269f6341", "week" : 42 }
{ "_id" : "17482f6759b", "week" : 42 }
{ "_id" : "7123d38759", "week" : 42 }
{ "_id" : "ff89b1fb", "week" : 42 }
它没有返回我在 $project 中指定的字段集
【问题讨论】:
-
您需要在第二个项目中再次包含它们。例如。成本:'$成本'
-
@sheilak,谢谢。因此,mongodb $cond 修复似乎不起作用。我正在返回 $dayOfMonth 以显示下订单 obj 的月份中的哪一天,但它仍然显示超出 2015 年 10 月 12 日范围的天数(即 2015 年 10 月 19 日甚至 2015 年 10 月 20 日)- 2015 年 10 月 18 日
-
更新了我的答案。您链接到的答案转换为星期一开始的一周,而不是 ISO 标准周。 ISO 标准周与 MongoDB 的不同之处在于它如何定义年初的第 1 周。对不起,我没有解决方案,但希望有几个指针可以更接近
标签: javascript mongodb mongoose