Nav*_*ath 12 java mongodb spring-data aggregation-framework spring-mongodb
对于MongoDB文档中的此示例,如何使用MongoTemplate编写查询?
db.sales.aggregate(
[
{
$group : {
_id : { month: { $month: "$date" }, day: { $dayOfMonth: "$date" }, year: { $year: "$date" } },
totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
}
]
)
Run Code Online (Sandbox Code Playgroud)
或者一般来说,我如何按计算字段分组?
Nei*_*unn 19
你可以先用"项目"来做这样的事情,但对我来说,$project
事前要求一个阶段有点反直觉:
Aggregation agg = newAggregation(
project("quantity")
.andExpression("dayOfMonth(date)").as("day")
.andExpression("month(date)").as("month")
.andExpression("year(date)").as("year")
.andExpression("price * quantity").as("totalAmount"),
group(fields().and("day").and("month").and("year"))
.avg("quantity").as("averavgeQuantity")
.sum("totalAmount").as("totalAmount")
.count().as("count")
);
Run Code Online (Sandbox Code Playgroud)
就像我说的那样,反直觉,因为你应该能够在$group
舞台上声明所有这些,但帮助者似乎不会这样工作.序列化有点搞笑(用数组包装日期运算符参数),但它似乎确实有效.但是,这仍然是两个管道阶段而不是一个.
这有什么问题?通过将阶段分开,阶段"项目"部分强制处理管道中的所有文档以获得计算字段,这意味着它在进入组阶段之前通过所有部分.
通过以两种形式运行查询,可以清楚地看到处理时间的差异.对于单独的项目阶段,在我的硬件上执行的时间比在"组"操作期间计算所有字段的查询要长三倍.
因此,似乎唯一正确构建此方法的方法是自己构建管道对象:
ApplicationContext ctx =
new AnnotationConfigApplicationContext(SpringMongoConfig.class);
MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");
BasicDBList pipeline = new BasicDBList();
String[] multiplier = { "$price", "$quantity" };
pipeline.add(
new BasicDBObject("$group",
new BasicDBObject("_id",
new BasicDBObject("month", new BasicDBObject("$month", "$date"))
.append("day", new BasicDBObject("$dayOfMonth", "$date"))
.append("year", new BasicDBObject("$year", "$date"))
)
.append("totalPrice", new BasicDBObject(
"$sum", new BasicDBObject(
"$multiply", multiplier
)
))
.append("averageQuantity", new BasicDBObject("$avg", "$quantity"))
.append("count",new BasicDBObject("$sum",1))
)
);
BasicDBObject aggregation = new BasicDBObject("aggregate","collection")
.append("pipeline",pipeline);
System.out.println(aggregation);
CommandResult commandResult = mongoOperation.executeCommand(aggregation);
Run Code Online (Sandbox Code Playgroud)
或者,如果所有这些看起来都很简洁,那么您始终可以使用JSON源并解析它.但当然,它必须是有效的JSON:
String json = "[" +
"{ \"$group\": { "+
"\"_id\": { " +
"\"month\": { \"$month\": \"$date\" }, " +
"\"day\": { \"$dayOfMonth\":\"$date\" }, " +
"\"year\": { \"$year\": \"$date\" } " +
"}, " +
"\"totalPrice\": { \"$sum\": { \"$multiply\": [ \"$price\", \"$quantity\" ] } }, " +
"\"averageQuantity\": { \"$avg\": \"$quantity\" }, " +
"\"count\": { \"$sum\": 1 } " +
"}}" +
"]";
BasicDBList pipeline = (BasicDBList)com.mongodb.util.JSON.parse(json);
Run Code Online (Sandbox Code Playgroud)