Spring MongoDB Aggregation Group - Не удается правильно запросить группу - PullRequest
1 голос
/ 28 мая 2019

У меня есть документ в MongoDB, который выглядит следующим образом.

{
    "_id" : ObjectId("5ceb812b3ec6d22cb94c82ca"),
    "key" : "KEYCODE001",
    "values" : [ 
        {
            "classId" : "CLASS_01",
            "objects" : [ 
                {
                    "code" : "DD0001"
                }, 
                {
                    "code" : "DD0010"
                }
            ]
        }, 
        {
            "classId" : "CLASS_02",
            "objects" : [ 
                {
                    "code" : "AD0001"
                }
            ]
        }
    ]
}

Я заинтересован в получении результата следующим образом.

{
    "classId" : "CLASS_01",
    "objects" : [ 
        {
            "code" : "DD0001"
        }, 
        {
            "code" : "DD0010"
        }
    ]
}

Чтобы получить это, я разработал конвейер агрегации в Robo 3T, который выглядит следующим образом. И работает как положено.

[
    {
        $match:{
            'key':'KEYCODE001'
        }
    },
    {
        "$unwind":{
            "path": "$values",
            "preserveNullAndEmptyArrays": true
        }
    },
    {
        "$unwind":{
            "path": "$values.objects",
            "preserveNullAndEmptyArrays": true
        }
    },
    {
        $match:{
            'values.classId':'CLASS_01'
        }
    },
    {
        $project:{
            'object':'$values.objects',
            'classId':'$values.classId'
        }
    },
    {
        $group:{
            '_id':'$classId',
            'objects':{
                $push:'$object'
            }
        }
    },
    {
        $project:{
            '_id':0,
            'classId':'$_id',
            'objects':'$$objects'
        }
    }
]

Теперь, когда я пытаюсь сделать то же самое в приложении SpringBoot, я не могу запустить его. Я закончил с ошибкой java.lang.IllegalArgumentException: Invalid reference '$complication'!. Вот что я сделал в Java до сих пор.

final Aggregation aggregation = newAggregation(
        match(Criteria.where("key").is("KEYCODE001")),
        unwind("$values", true),
        unwind("$values.objects", true),
        match(Criteria.where("classId").is("CLASS_01")),
        project().and("$values.classId").as("classId").and("$values.objects").as("object"),
        group("classId", "objects").push("$object").as("objects").first("$classId").as("_id"),
        project().and("$_id").as("classId").and("$objects").as("objects")
);

Что я делаю не так? После исследования я обнаружил, что несколько полей в группе не работают или что-то в этом роде (см. этот вопрос ). Итак, возможно ли то, что я сейчас делаю, в Spring Boot?

1 Ответ

1 голос
/ 28 мая 2019

После нескольких часов отладки + проб и ошибок обнаружил, что работает следующее решение.

final Aggregation aggregation = newAggregation(
        match(Criteria.where("key").is("KEYCODE001")),
        unwind("values", true),
        unwind("values.objects", true),
        match(Criteria.where("values.classId").is("CLASS_01")),
        project().and("values.classId").as("classId").and("values.objects").as("object"),
        group(Fields.from(Fields.field("_id", "classId"))).push("object").as("objects"),
        project().and("_id").as("classId").and("objects").as("objects")
);

Все сводится к group(Fields.from(Fields.field("_id", "classId"))).push("object").as("objects") тому, что вводит org.springframework.data.mongodb.core.aggregation.Fields объект, который упаковывает список org.springframework.data.mongodb.core.aggregation.Field объектов. В пределах Field имя поля и цель могут быть инкапсулированы. Это привело к следующему конвейеру, который соответствует ожидаемому.

[
    {
        "$match" :{
            "key" : "KEYCODE001"
        }
    }, 
    {
        "$unwind" :{
            "path" : "$values", "preserveNullAndEmptyArrays" : true
        }
    }, 
    {
        "$unwind" :{
            "path" : "$values.objects", "preserveNullAndEmptyArrays" : true
        }
    }, 
    {
        "$match" :{
            "values.classId" : "CLASS_01"
        }
    }, 
    {
        "$project" :{
            "classId" : "$values.classId", "object" : "$values.objects"
        }
    }, 
    {
        "$group" :{
            "_id" : "$classId",
            "objects" :{
                "$push" : "$object"
            }
        }
    }, 
    {
        "$project" :{
            "classId" : "$_id", "objects" : 1
        }
    }
]

Кроме того, решил, что нет необходимости использовать знак $ везде и всюду.

...