首先看一下原始文档(单个)
db.xxx.aggregate(
[
{
$match: {
"createDate": {
$gt: 1581091200000,
$lt: 1581174511000
},
"rangerLocationList.iTime": {
$gt: 1581091200000,
$lt: 1581174511000
},
"xxxId": 10051,
}
},
{
$project: {
_id: 0,
createDate: 1,
rangerLocationList: 1,
date2StrOfNewDate: {
$dateToString: {
format: "%H",
date: {
"$add": [new Date(0), "$createDate", 28800000]
}
}
},
date2Str: {
$dateToString: {
format: "%Y-%m-%d %H:%M:%S:%L",
date: {
"$add": [new Date(0), "$createDate", 28800000]
}
}
},
}
},
{
$unwind: "$rangerLocationList"
},
]
)
结果如下:
Aggregation aggregation = newAggregation(
match(Criteria.where("createDate").gte(begin.getTime()).lte(end.getTime()).and("rangerLocationList.dataDate").gte(begin.getTime()).lte(end.getTime()).and("xxxId").is(xxxId).and("xxxxId").is(xxxxId))
,unwind("rangerLocationList")
,project("rangerLocationList").andExclude("_id").andExpression("{$dateToString:{format:'%H',date:{$add:{new Date(0),'$createDate',28800000}}}}").as("date2StrOfNewDate")
);
AggregationResults<xxx> aggregate = mongoTemplate.aggregate(aggregation, xxx.class, xxx.class);
可是却报如下错误(主要报错如下,其他没用的省略)
org.springframework.expression.spel.SpelEvaluationException: EL1003E: A problem occurred whilst attempting to construct an object of type 'Date' using arguments '(java.lang.Integer)'
... ...
... ...
... ...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1005E: Type cannot be found 'Date'
... ...
后来找到是因为spel表达式的原因,在spel表达式中,类实例化同样使用java关键字“new”,类名必须是全限定名,但java.lang包内的类型除外,如String、Integer。所以把java代码改动如下:
Aggregation aggregation = newAggregation(
match(Criteria.where("createDate").gte(begin.getTime()).lte(end.getTime()).and("rangerLocationList.dataDate").gte(begin.getTime()).lte(end.getTime()).and("xxxId").is(xxxId).and("xxxxId").is(xxxxId))
,unwind("rangerLocationList")
,project("rangerLocationList").andExclude("_id").andExpression("{$dateToString:{format:'%H',date:{$add:{new java.util.Date(0),'$createDate',28800000}}}}").as("date2StrOfNewDate")
);
AggregationResults<xxx> aggregate = mongoTemplate.aggregate(aggregation, xxx.class, xxx.class);
然后在本地用idea调试确实能查询出来不报错
但是发到测试服务器上的时候,又报错了。
!可以看到和上面第一次的错误神似却不相试,主要是因为在new java.util.Date(0)里面的0默认是Integer类型的,需要转成Long类型的,所以做了以下修改
Aggregation aggregation = newAggregation(
match(Criteria.where("createDate").gte(begin.getTime()).lte(end.getTime()).and("rangerLocationList.dataDate").gte(begin.getTime()).lte(end.getTime()).and("xxxId").is(xxxId).and("xxxxId").is(xxxxId))
,unwind("rangerLocationList")
,project("rangerLocationList").andExclude("_id").andExpression("{$dateToString:{format:'%H',date:{$add:{new java.util.Date(0l),'$createDate',28800000}}}}").as("date2StrOfNewDate")
);
AggregationResults<xxx> aggregate = mongoTemplate.aggregate(aggregation, xxx.class, xxx.class);
发到服务器正确无误(sql如下,和想象中一样)
mongodb的聚合框架(aggregate)提供了很多修改器用来修改去获取IOSDate类型的字段的年、月、日、时、分、秒、等;同时mongodb也提供了相关的修改器去把IOSDate类型的时间转换为通常我们可以接受的时间格式;
$dayOfYear: 返回该日期是这一年的第几天。(全年366天)
$dayOfMonth: 返回该日期是这一个月的第几天。(1到31)
$dayOfWeek: 返回的是这个周的星期几。(1:星期日,7:星期六)
$year: 返回该日期的年份部分 $month: 返回该日期的月份部分(between 1and12.)
$week: 返回该日期是所在年的第几个星期(between 0and53)
$hour: 返回该日期的小时部分 $minute: 返回该日期的分钟部分
$second: 返回该日期的秒部分(以0到59之间的数字形式返回日期的第二部分,但可以是60来计算闰秒。)
$millisecond:返回该日期的毫秒部分(between 0and999.)
$dateToString: { $dateToString: { format: , date: } }
formatString:需要返回的日期式,日期格式通常为以:
%Y Year (4 digits, zero padded) 0000-9999
%m Month (2 digits, zero padded) 01-12
%d Day of Month (2 digits, zero padded) 01-31
%H Hour (2 digits, zero padded, 24-hour clock) 00-23
%M Minute (2 digits, zero padded) 00-59
%S Second (2 digits, zero padded) 00-60
%L Millisecond (3 digits, zero padded) 000-999
%j Day of year (3 digits, zero padded) 001-366
%w Day of week (1-Sunday, 7-Saturday) 1-7
%U Week of year (2 digits, zero padded) 00-53
%% Percent Character as a Literal