Spring-数据未总结季度业绩

Spring-Data not summing up the quarterly results

我是 Mongodb 和 spring-data 的新手,我参考了这个 Whosebug link and this link using $cond operator in spring data 并在下面构建了这个代码片段,用于检索季度销售额在 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());
            }

问题不是对售出的单位求和。请让我知道 spring 数据哪里出了问题。但是这个查询使用 robomongo 获得了所需的结果。

此致

克里斯

如果您说它在另一个客户端中有效,那么很可能在转换过程中丢失了一些东西。您当然可以在此处清理一些内容以使其更加简化。

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

[
    { "$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"))
        )
    )
);

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

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 结果,那么它是字段命名或 "type",其中字段的名称不同或实际上是一个字符串。但是相同的语句应该以类似的方式在任何其他客户端中失败,唯一的补救措施是修复命名或 "type" 适当的。

这当然是您所做工作的 "cleaner" 方法。 "math" 对于索引季度来说是合理的,甚至可以通过简单的映射适当地适应其他 "financial quarters"。正如此处管道阶段的整合提供了与数据的整体大小一致的显着性能提升,因为 $project 意味着不必要的数据传递只是为了预调整字段,而您不需要想要。

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