【问题标题】:Using multiple facets in MongoDB Spring Data在 MongoDB Spring Data 中使用多个方面
【发布时间】:2019-04-19 00:53:54
【问题描述】:

我想在一个聚合中运行多个方面以节省数据库往返。这是我的弹簧数据代码:

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
    }
]

}

任何帮助将不胜感激。

【问题讨论】:

  • 您的问题解决了吗?

标签: mongodb spring-boot aggregation facet


【解决方案1】:

您可以使用.and() 和.as() 方法链接多个方面操作。您应该将第二个facet 方法替换为and 方法,如下所示。

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")

【讨论】:

  • 这很有帮助,可以节省很多时间。
猜你喜欢
  • 2015-10-19
  • 2018-07-13
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
相关资源
最近更新 更多