Всъщност можете първо да направите нещо подобно с „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
етап, но помощниците изглежда не работят по този начин. Сериализацията изглежда малко смешна (обвива аргументите на оператора за дата с масиви), но изглежда работи. Но все пак това са два етапа на тръбопровод, а не един.
Какъв е проблемът с това? Е, като разделя етапите на етапите, частта „проект“ принуждава обработката на всички документи в конвейера, за да получи изчислените полета, което означава, че преминава през всичко, преди да премине към груповия етап.
Разликата във времето за обработка може ясно да се види, като стартирате заявките и в двете форми. С отделен етап на проекта изпълнението на моя хардуер отнема три пъти повече време от заявката, при която всички полета се изчисляват по време на операцията „група“.
Така че изглежда единственият настоящ начин да се конструира това правилно е като се изгради сам тръбопроводният обект:
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);