【问题标题】:Conditional query with spring mongotemplate使用 spring mongotemplate 进行条件查询
【发布时间】:2016-08-03 06:01:20
【问题描述】:

我想使用条件查询。

这是我的查询

db.projects.aggregate([
{
    "$group": {
        "_id": "$iecode",
        "treatmentArms": { "$first": "$evaluationDTOList" }
    }
},
{ "$unwind": "$treatmentArms" },
{
    "$group": {
        "_id": null,
        "Package": { 
            "$sum": { 
               "$cond": [ 
                   { "$eq": [ "$treatmentArms.mechanismOrPkg", "Package" ] }, 
                   1, 0
                ] 
            }
        },
        "Constraint-relaxing mechanisms": { 
            "$sum": { 
               "$cond": [ 
                    { 
                        "$and": [
                            { "$eq": [ "$treatmentArms.mechanismOrPkg", "Mechanism" ] },
                            { "$eq": [ "$treatmentArms.mechanismTested1", "Constraint-relaxing mechanisms" ] }
                        ]
                    }, 
                    1, 
                    0 ]
            }
        },
        "Delivery mechanisms": { 
            "$sum": { 
               "$cond": [ 
                    { 
                        "$and": [
                            { "$eq": [ "$treatmentArms.mechanismOrPkg", "Mechanism" ] },
                            { "$eq": [ "$treatmentArms.mechanismTested1", "Delivery mechanisms" ] }
                        ]
                    }, 
                    1, 
                    0 ]
            }
        },
        "Other": { 
            "$sum": { 
               "$cond": [ 
                    { 
                        "$and": [
                            { "$eq": [ "$treatmentArms.mechanismOrPkg", "Mechanism" ] },
                            { "$eq": [ "$treatmentArms.mechanismTested1", "Other" ] }
                        ]
                    }, 
                    1, 
                    0 ]
            }
        }
    }
}
])

这是我的java代码

DBObject groupByIECode = new BasicDBObject("$group",
                new BasicDBObject("_id", new BasicDBObject("iecode","$iecode")).append("treatmentArms",new BasicDBObject("$first","$evaluationDTOList")));
        System.out.println("groupByIECode: "+groupByIECode.toString());

        DBObject unwind = new BasicDBObject("$unwind","$treatmentArms");
        System.out.println("unwind: "+unwind.toString());


        DBObject finalCalculation = new BasicDBObject("$group",new BasicDBObject("_id",null))
                                    .append(
                                            "Package", new BasicDBObject(
                                                "$sum", new BasicDBObject(
                                                    "$cond", new Object[]{
                                                        new BasicDBObject(
                                                            "$eq", new Object[]{ "$treatmentArms.mechanismOrPkg", "Package"}
                                                        ),
                                                        1,
                                                        0
                                                    }
                                                )
                                            )
                                        );

        System.out.println("finalCalculation: "+finalCalculation);
        final AggregationOutput output = projects.aggregate(match,groupByIECode,unwind,finalCalculation);

它给了我MongoException$DuplicateKey

后来发现spring mongotemplate不支持$cond操作符。那么如何使用spring mongotemplate 实现这个条件查询。

This 链接有一些解释,但没有显示完整的实现

【问题讨论】:

    标签: spring mongodb aggregation-framework spring-mongodb


    【解决方案1】:

    来自documentation,使用 Spring Data MongoDB 支持 MongoDB 聚合框架的典型示例如下所示:

    import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
    
    Aggregation agg = newAggregation(
        pipelineOP1(),
        pipelineOP2(),
        pipelineOPn()
    );
    
    AggregationResults<OutputType> results = mongoTemplate.aggregate(agg,
        "INPUT_COLLECTION_NAME", OutputType.class);
    List<OutputType> mappedResult = results.getMappedResults();
    

    请注意,如果您将输入类作为第一个参数提供给 newAggregation 方法 MongoTemplate 将派生的名称 此类的输入集合。否则,如果您不指定 输入类,您必须提供输入集合的名称 明确地。如果提供了输入类和输入集合 后者优先。


    对于您的查询,创建一个实现 AggregationOperation 接口的解决方法,以接收一个 DBObject,它表示具有 $cond 运算符:

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

    然后将$group 操作实现为聚合管道中的DBObject,与您拥有的相同:

    DBObject operation = (DBObject) new BasicDBObject("$group", new BasicDBObject("_id", null))
        .append(
            "Package", new BasicDBObject(
                "$sum", new BasicDBObject(
                    "$cond", new Object[]{
                        new BasicDBObject(
                            "$eq", new Object[]{ "$treatmentArms.mechanismOrPkg", "Package"}
                        ),
                        1,
                        0
                    }
                )
            )
        );
    

    然后您可以将其用作:

    import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
    
    GroupAggregationOperation groupOp = new GroupAggregationOperation(operation);
    Aggregation agg = newAggregation(
        group("iecode").first("treatmentArms").as("treatmentArms"),
        unwind("treatmentArms"),
        groupOp 
    );
    AggregationResults<Entity> results = mongoTemplate.aggregate(agg, Entity.class); 
    List<Entity> entities = results.getMappedResults();
    

    【讨论】:

    • 我可以从Aggregation 对象中获得DBObject。其实我不是类(实体)。
    • 我的意思是在哪里指定我想要触发查询的集合名称。
    • @HalfBloodPrince 我已经用documentation 中的规范示例更新了我的答案,我鼓励你去看看。
    • 附加另一个带有条件的 DBObject
    • 没有。只需将其他 $group 对象键附加到现有 DBObjectDBObject operation = (DBObject) new BasicDBObject("$group", new BasicDBObject("_id", null)).append("Package", new ...).append("Constraint-relaxing mechanisms", new ...).append("Delivery mechanisms", new ...).append(...
    猜你喜欢
    • 2017-03-28
    • 2019-10-14
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多