Thi*_*sen 5 java mongodb spring-mongo mongodb-query aggregation-framework
要直接,我该怎么做:
group._id = {
year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] },
month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] },
day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] }
};
Run Code Online (Sandbox Code Playgroud)
用spring数据
我已经尝试了这个和其他一些形式并没有成功
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(c),
Aggregation.project("programa", "custo", "duracao", "dataHora")
.andExpression("dataHora").minus(25200000).extractDayOfMonth().as("dia")
.andExpression("dataHora").minus(25200000).extractMonth().as("mes")
.andExpression("dataHora").minus(25200000).extractYear().as("ano"),
Aggregation.group("programa", "ano", "mes", "dia")
.count().as("count")
.sum("custo").as("valorTotal")
.sum("duracao").as("duracaoTotal")
.first("dataHora").as("dataHora"),
Aggregation.sort(Direction.ASC, "dataHora")
);
Run Code Online (Sandbox Code Playgroud)
我需要在mongodb中按天,月和年进行分组,否则我需要在代码中转换所有这些分组数据.
提前致谢
你正在为一个$project阶段中的字段计算做的事情遇到spring mongo的限制,事实上你可能已经单独编写,$project因为你发现你现在也不能直接在自定义命名字段中进行投影.$group _id
因此,最好不要将这一切保留在内$group,以及使用不同的方法将调整后的日期四舍五入到当地时间.
因此,更好的写作方式$group是:
{ "$group": {
"_id": {
"programa": "$programa",
"dataHora": {
"$add": [
{ "$subtract": [
{ "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] },
{ "$mod": [
{ "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] },
1000 * 60 * 60 * 24
]}
]},
new Date(0)
]
}
},
"count": { "$sum": 1 },
"valorTotal": { "$sum": "$custo" },
"duracaoTotal": { "$sum": "$duracao" },
"dataHora": { "$first": "$dataHora" }
}}
Run Code Online (Sandbox Code Playgroud)
当然要使用spring-mongo这种结构,你需要一个可以定义的聚合阶段操作的自定义实现DBObject:
public class CustomGroupOperation implements AggregationOperation {
private DBObject operation;
public CustomGroupOperation (DBObject operation) {
this.operation = operation;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你在上下文中使用这样的:
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(c),
new CustomGroupOperation(
new BasicDBObject("$group",
new BasicDBObject("_id",
new BasicDBObject("programa","$programa")
.append("dataHora",
new BasicDBObject("$add",Arrays.asList(
new BasicDBObject("$subtract",Arrays.asList(
new BasicDBObject("$subtract",Arrays.asList(
new BasicDBObject("$subtract",Arrays.asList(
"$dataHora", new Date(0)
)),
25200000
)),
new BasicDBObject("$mod",Arrays.asList(
new BasicDBObject("$subtract",Arrays.asList(
new BasicDBObject("$subtract",Arrays.asList(
"$dataHora", new Date(0)
)),
25200000
)),
1000 * 60 * 60 * 24
))
)),
new Date(0)
))
)
)
.append("count",new BasicDBObject("$sum",1))
.append("valorTotal",new BasicDBObject("$sum","$custo"))
.append("duracaoTotal",new BasicDBObject("$sum","$duracao"))
.append("dataHora",new BasicDBObject("$first","$dataHora"))
)
),
Aggregation.sort(Direction.ASC,"_id.dataHora")
);
Run Code Online (Sandbox Code Playgroud)
由于自定义类是从内置辅助方法使用的相同基本类中抽象出来的,因此它可以与它们一起使用,如图所示.
这里使用日期数学的基本过程是如何当你$subtract从另一个BSON Date对象中获得一个BSON Date对象时,结果是差异的毫秒数,在这种情况下是从仅提取毫秒值的纪元日期(Date(0)).这允许您通过modulo($mod)从一天中的毫秒数开始舍入到当前日期值.
就像您最初尝试的那样,当您$add将该毫秒值传递给BSON Date对象时,返回的值又是BSON日期.因此,添加到表示纪元的对象会返回一个新的日期对象,但会四舍五入到当前日期.
这通常比通过日期聚合运算符提取部件更有用,而且编码时间也要短一些,特别是在调整UTC的时间时,就像在这里一样.
虽然$group这里的构造比spring mongo试图避免的辅助函数更简洁,但最终它比运行一个单独的$project阶段来转换你在$group阶段中真正只想要的字段值要高效得多无论如何.
| 归档时间: |
|
| 查看次数: |
2186 次 |
| 最近记录: |