春季数据不总结季度结果



我是Mongodb和spring-data的新手,我在spring数据中使用$cond运算符参考了这个stackoverflow链接分组,并在下面构建了这个代码片段,用于检索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获得所需的结果。


克丽丝

如果您说它在另一个客户端中工作,那么可能在事务中丢失了一些东西。你当然可以在这里清理一些东西,使它更简化。

我通常可以建议一个更有效的"数学"方法来确定当前季度,而不是当前嵌套的条件语句,如果没有别的,它使事情变得更加清晰。除了"效率"之外,你不应该在$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聚合helper发生冲突的方式实现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意味着通过数据进行不必要的传递,只是为了预先调整字段,这是您不想要的。

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

最新更新