1

条件付きクエリを使用したい。

これが私のクエリです

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

$cond後で、 でoperator がサポートされていないことがわかりましたspring mongotemplate。では、この条件付きクエリをspring mongotemplate.

このリンクにはいくつかの説明がありますが、完全な実装は示されていません

4

1 に答える 1

1

documentationから、MongoDB Aggregation Framework の Spring Data 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 はこのクラスから入力コレクションの名前を派生させることに注意してください。入力クラスを指定しない場合は、入力コレクションの名前を明示的に指定する必要があります。input-class と input-collection が指定されている場合、後者が優先されます。


クエリに対して、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();
于 2016-08-03T07:01:56.243 に答える