实际上,你可以先使用"project"完成这样的操作,但对我来说,在此之前需要$project
阶段有点不太直观:
你实际上可以像这样首先使用 "project",但是对我来说,在此之前要求一个$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")
);
就像我说的那样,这看起来不符合直觉,因为你应该只需要在$group
阶段下声明所有内容,但是助手似乎不能按照这种方式工作。序列化结果有点奇怪(用数组包装了日期操作符参数),但它似乎可以工作。但仍然需要使用两个管道阶段而不是一个。
这个有什么问题呢?好吧,通过分离“project”部分,处理整个管道中的所有文档以获得计算字段,这意味着它必须在进入组阶段之前通过所有东西。
运行两种形式的查询可以明显地看到处理时间上的差异。使用单独的project阶段,在我的硬件上执行所需的时间是在所有字段在“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);
如果你觉得这些都太简洁了,那么你可以使用 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);