我想在一个聚合中运行多个方面以节省数据库往返。这是我的spring数据代码:
final BalancesDTO total
= this.mongoTemplate.aggregate(
newAggregation(
/*
* Get all fund transactions for this user
*/
match(where("userId").is(userId)),
/*
* Summarize Confirmed Debits
*/
facet( match(where("entryType").is(EntryType.DEBIT)
.andOperator(where("currentStatus").is(TransactionStatus.CONFIRMED))),
unwind("history"),
match(where("history.status").is(TransactionStatus.CONFIRMED)),
project().andExpression("history.amount").as("historyAmount"),
group().sum("historyAmount").as("total"),
project("total")
).as("totalConfirmedDebits"),
/*
* Summarize Confirmed Credits
*/
facet( match(where("entryType").is(EntryType.CREDIT)
.andOperator(where("currentStatus").is(TransactionStatus.CONFIRMED))),
unwind("history"),
match(where("history.status").is(TransactionStatus.CONFIRMED)),
project().andExpression("history.amount").as("historyAmount"),
group().sum("historyAmount").as("total"),
project("total")
).as("totalConfirmedCredits")
),
FundTransactions.class,
BalancesDTO.class)
.getUniqueMappedResult();
LOGGER.debug("total : {}",total.getTotalConfirmedDebits().get(0).getTotal());
当我运行上面的代码时,它给了我以下异常:
java.lang.IllegalArgumentException: Invalid reference 'history'!
at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:100) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.ExposedFieldsAggregationOperationContext.getReference(ExposedFieldsAggregationOperationContext.java:72) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.UnwindOperation.toDocument(UnwindOperation.java:94) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.AggregationOperationRenderer.toDocument(AggregationOperationRenderer.java:55) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.FacetOperation$Facet.toDocuments(FacetOperation.java:224) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.FacetOperation$Facets.toDocument(FacetOperation.java:168) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.FacetOperation.toDocument(FacetOperation.java:87) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.AggregationOperationRenderer.toDocument(AggregationOperationRenderer.java:55) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.aggregation.Aggregation.toDocument(Aggregation.java:585) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate$BatchAggregationLoader.prepareAggregationCommand(MongoTemplate.java:3124) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate$BatchAggregationLoader.aggregate(MongoTemplate.java:3107) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1937) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate.aggregate(MongoTemplate.java:1832) ~[spring-data-mongodb-2.0.7.RELEASE.jar:2.0.7.RELEASE]
at io.tradehack.shared.fundtransactions.FundTransactionsRepositoryImpl.getFundBalances(FundTransactionsRepositoryImpl.java:41) ~[classes/:na]
at io.tradehack.shared.fundtransactions.FundTransactionsRepositoryImpl$$FastClassBySpringCGLIB$$89f7e1a0.invoke(<generated>) ~[classes/:na]
但是有趣的是,如果我删除了第二个方面,它就可以工作。发生此异常的原因可能是什么?
以下是我要运行的等效mongodb命令:
db.runCommand(
{ "aggregate" : "FundTransactions",
"pipeline" : [{ "$match" : { "userId" : "6cd984b9-1c17-402b-be9c-70614e0b8b8e"} },
{ "$facet" : { "totalConfirmedDebits" : [{ "$match" : { "entryType" : "DEBIT",
"$and" : [{ "currentStatus" : "CONFIRMED" }] } },
{ "$unwind" : "$history" },
{ "$match" : { "history.status" : "CONFIRMED" } },
{ "$project" : { "historyAmount" : "$history.amount" } },
{ "$group" : { "_id" : null,
"total" : { "$sum" : "$historyAmount" } } },
{ "$project" : { "total" : 1 } }],
"totalConfirmedCredits" : [{ "$match" : { "entryType" : "CREDIT",
"$and" : [{ "currentStatus" : "CONFIRMED" }] } },
{ "$unwind" : "$history" },
{ "$match" : { "history.status" : "CONFIRMED" } },
{ "$project" : { "historyAmount" : "$history.amount" } },
{ "$group" : { "_id" : null,
"total" : { "$sum" : "$historyAmount" } } },
{ "$project" : { "total" : 1 } }]
}
}],
"cursor" : { "batchSize" : 2147483647 } }
)
下面是示例数据:
{
"_id" : "dfe9dd63-6689-4e9f-8494-24efa6191db1",
"userId" : "6cd984b9-1c17-402b-be9c-70614e0b8b8e",
"entryType" : "DEBIT",
"type" : "DEPOSIT",
"createdDateTime" : ISODate("2018-11-11T03:00:00.000+00:00"),
"currentVersion" : 2,
"currentStatus" : "CONFIRMED",
"history" : [
{
"referenceId" : null,
"currency" : "USD",
"amount" : 1000000,
"comments" : "Initial fundings",
"updatedDateTime" : ISODate("2018-11-11T03:00:00.000+00:00"),
"status" : "PENDING",
"version" : 1
},
{
"referenceId" : null,
"currency" : "USD",
"amount" : 1001000,
"comments" : "Initial fundings",
"updatedDateTime" : ISODate("2018-11-11T04:00:00.000+00:00"),
"status" : "CONFIRMED",
"version" : 2
}
]
}
任何帮助将不胜感激。
答案 0 :(得分:1)
You can chain multiple facet operation using the .and()
and .as()
methods. You should replace the second facet
method with the and
method as below.
FacetOperation facets = facet(match(where("entryType").is(EntryType.DEBIT)
.andOperator(where("currentStatus").is(TransactionStatus.CONFIRMED))),
unwind("history"),
match(where("history.status").is(TransactionStatus.CONFIRMED)),
project().andExpression("history.amount").as("historyAmount"),
group().sum("historyAmount").as("total"),
project("total")
).as("totalConfirmedDebits"),
/*
* Summarize Confirmed Credits
*/
.and(match(where("entryType").is(EntryType.CREDIT)
.andOperator(where("currentStatus").is(TransactionStatus.CONFIRMED))),
unwind("history"),
match(where("history.status").is(TransactionStatus.CONFIRMED)),
project().andExpression("history.amount").as("historyAmount"),
group().sum("historyAmount").as("total"),
project("total")
).as("totalConfirmedCredits")