【问题标题】:Spring-Data not summing up the quarterly resultsSpring-Data 未总结季度业绩
【发布时间】:2015-12-17 19:44:20
【问题描述】:

我是 Mongodb 和 spring-data 的新手,我参考了这个 stackoverflow 链接 grouping quarterly wise 和这个链接 using $cond operator in spring data 并在下面构建了这个代码 sn-p,用于在 mongodb 中检索季度销售报告:

String pipeline =   "{$project:{_id:1,'unitsSold':1,'dateSold':1,'results': 1 ,
  'productName': 1, 'year':{$year:['$dateSold']},    "+
       "'quarter':{$cond:[{$lte:[{$month:'$dateSold'},3]},"+
                         "'first'," +
                         "{$cond:[{$lte:[{$month:'$dateSold'},6]},"+
                                 "'second',"+
                                 "{$cond:[{$lte[{$month:'$dateSold'},9]},"+"'third',"+
                                         "'fourth']}]}]}}},"+
"{$group:{'_id':{ 'year':'$year', 'quarter':'$quarter'},  
'unitsSold': { $sum: '$unitsSold' },'results':{$push:'$$ROOT'}}}";



 DBObject operation = (DBObject)JSON.parse (pipeline);

TypedAggregation<SampleReport> aggregation =newAggregation(SampleReport.class,
new DBObjectAggregationOperation(operation)
);

AggregationResults<SampleReport> result =mongoTemplate.aggregate(aggregation, SampleReport.class);
List<SampleReport> list = result.getMappedResults();
for(SampleReport r : list)
            {
                System.out.println (r.getProductName() + " : " + r.getUnitsSold() + " : " + r.getQuarter() +":: "+r.getYear());
            }

问题不在于总结已售出的单位。请让我知道我的弹簧数据哪里出错了。但是这个查询使用 robomongo 获得了所需的结果。

问候

克里斯

【问题讨论】:

    标签: java mongodb mongodb-query aggregation-framework spring-data-mongodb


    【解决方案1】:

    如果您说它适用于其他客户端,则可能在交易中丢失了某些东西。您当然可以在此处清理一些内容以使其更加简化。

    我一般可以建议一种更有效的“数学”方法来确定当前季度,而不是当前嵌套的条件语句,好像没有其他方法可以让事情变得更清晰。除了“效率”之外,您不应该只在 $group 之前使用 $project,将所有内容简单地组合到一个阶段是合乎逻辑的:

    [
        { "$group": {
            "_id": {
                "year": { "$year": "$dateSold" },
                "quarter": {
                    "$add": [
                        { "$subtract": [
                            { "$divide": [{ "$subtract": [{ "$month": "$dateSold" },1]},3]},
                            { "$mod": [
                                { "$divide": [{ "$subtract": [{ "$month": "$dateSold" },1]},3]},
                                1
                            ]}
                        ]},
                        1
                    ]
                }
            },
            "unitsSold": { "$sum": "$unitsSold" }
        }}
    ]
    

    如果您确实需要,请务必添加您的"$push": "$$ROOT",但减少涉及的逻辑并将所有内容放入一个合理的流水线阶段主要是这里的重点。

    下一个阶段是我强烈建议您在本机上编写代码。虽然您可能很容易认为您有一个可以使用的 JSON 表示法,但您会发现这既不灵活,也不提供非常好的可读性来放置长字符串并依赖于解析它们。此外,您通常会希望在某个阶段插入局部变量

    Aggregation aggregation = newAggregation(
        new CustomGroupOperation(
            new BasicDBObject("$group",
                new BasicDBObject("_id",
                    new BasicDBObject("year",new BasicDBObject("$year","$dateSold"))
                        .append("quarter",new BasicDBObject(
                            "$add",Arrays.asList(
                                new BasicDBObject("$subtract",Arrays.asList(
                                    new BasicDBObject("$divide",Arrays.asList(
                                        new BasicDBObject("$subtract",Arrays.asList(
                                            new BasicDBObject("$month","$dateSold"),
                                            1
                                        )),
                                        3
                                    )),
                                    new BasicDBObject("$mod",Arrays.asList(
                                        new BasicDBObject("$divide", Arrays.asList(
                                            new BasicDBObject("$subtract",Arrays.asList(
                                                new BasicDBObject("$month", "$dateSold"),
                                                1
                                            )),
                                            3
                                        )),
                                        1
                                    ))
                                )),
                                1
                            )
                        ))
                )
                .append("unitsSold", new BasicDBObject("$sum", "$unitsSold"))
            )
        )
    );
    

    您似乎还抽象了一些其他代码,但我个人更喜欢以不会与在 newAggregation 构造中使用其他 spring-mongo 聚合助手冲突的方式来实现 CustomGroupOperation

    public class CustomGroupOperation implements AggregationOperation {
        private DBObject operation;
    
        public CustomGroupOperation (DBObject operation) {
            this.operation = operation;
        }
    
        @Override
        public DBObject toDBObject(AggregationOperationContext context) {
            return context.getMappedObject(operation);
        }
    }
    

    但正如最初所说,如果您得到0 结果,那么它是字段命名或“类型”,其中字段名称不同,或者实际上是一个字符串。但是相同的语句在任何其他客户端中都会以类似的方式失败,唯一的补救措施是适当地修复命名或“类型”。

    这对于您正在做的事情来说无疑是一种“更清洁”的方法。 “数学”对于索引季度来说是合理的,甚至可以通过简单的映射适当地适应其他“财务季度”。正如此处的管道阶段合并提供了与数据整体大小一致的显着性能提升,因为$project 意味着不必要的数据传递只是为了预先调整字段,这是您不想要的。

    修复定义和执行,然后检查您的字段和数据以确保所有内容都正确命名和键入。

    【讨论】:

    • 感谢您的回答,我遇到了一个例外:管道阶段规范对象必须只包含一个字段。请让我知道我错在哪里。
    • @chiku 您需要使用提供的代码,因为您显然正在做一些不同的事情来获得该特定错误。首先按原样使用它,因为这回答了您提出的问题。如果您想更改并遇到问题,请ask another question 而不是在这里发表评论,因为我们看不到您在做什么..
    • @user1503117 你是谁?这不是您的问题,还是您是使用两个帐户的同一用户?如果您是同一个人,请使用您发布的帐户进行回复,否则会造成混淆。无论如何,只是说“例外”而没有其他细节并不能告诉我任何事情。上面给出的清单应该没有错。
    • Blakes,用户是我的开发人员@我的办公室,他已经尝试过你的解决方案,但它没有用,当在 robomongo 中运行聚合查询时,它在使用 spring 数据运行时效果很好,它给出了这个异常提到。请提供解决方案。克里斯
    • @chiku 我又要问“什么例外?”。您需要编辑问题以显示正在运行的内容以及遇到的异常的详细信息。我几乎可以保证这里的列表没有错,实际上它的实施方式存在另一个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2023-02-07
    • 2018-06-01
    • 2017-12-09
    相关资源
    最近更新 更多