Spring-Data没有总结季度业绩

时间:2015-09-21 07:30:03

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

我是Mongodb和spring-data的新手,我参考了这个stackoverflow链接grouping quarterly wise和此链接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());
            }

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

此致

克里斯

1 个答案:

答案 0 :(得分:1)

如果你说它在另一个客户端工作,那么很可能在转换中丢失了一些东西。有些事情你可以在这里清理,以使其更简化。

我能否建议更有效率的数学&#34;确定当前季度而不是当前嵌套条件语句的方法,好像没有其他任何东西可以使事情变得更加清晰。除了&#34;效率&#34;你不应该在$project之前使用$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"))
        )
    )
);

你似乎也抽象了一些其他代码,但我个人更喜欢以一种不会与CustomGroupOperation构造中使用其他spring-mongo聚合助手相冲突的方式实现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结果,那么它的字段命名或&#34;键入&#34;字段名称不同或实际上是字符串。但是,相同的声明应该以类似的方式在任何其他客户端失败,并且唯一的补救措施是修复命名或&#34;类型&#34;酌情。

这当然是一个清洁&#34;接近你正在做的事情。 &#34;数学&#34;对于指数化的季度来说是合理的,甚至可以适应其他金融季度&#34;通过简单的映射适当。由于$project意味着不需要通过数据只是为了预先调整字段,因此这里的流水线阶段的合并可以提供显着的性能提升,而不是 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result- prefixes="msxsl" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"> <!-- Copy all attributes and elements to the output. --> <xsl:template match="@*|*"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:apply-templates select="*" /> </xsl:copy> </xsl:template> <xsl:output method="xml" indent="yes" /> <xsl:key name="exe-search" match="wix:Component[contains(wix:File/@Source, 'Program.exe" use="@Id" /> <xsl:template match="wix:Component[key('exe-search', @Id)]" /> <xsl:template match="wix:ComponentRef[key('exe-search', @Id)]" /> </xsl:stylesheet> 。 ;想要。

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