【问题标题】:Spring MongoDB Aggregation Group - Can't get the group query rightSpring MongoDB Aggregation Group - 无法正确获取组查询
【发布时间】:2019-05-28 06:26:04
【问题描述】:

我在 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")
);

我做错了什么?经过研究,我发现组中的多个字段不起作用或类似的东西(请参阅this question)。那么,我目前在 Spring Boot 中所做的事情是否可行?

【问题讨论】:

    标签: java spring mongodb group-by aggregate


    【解决方案1】:

    经过数小时的调试+反复试验,发现以下解决方案有效。

    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.Field 对象列表的org.springframework.data.mongodb.core.aggregation.Fields 对象。在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
            }
        }
    ]
    

    此外,认为没有必要在任何地方和任何地方使用$ 符号。

    【讨论】:

    • 感谢您的帖子,我找到了一个非常相似问题的解决方案!
    • 遇到类似问题的人,请查看this post
    • Mongo 可以很酷且无需模型,但它的查询语言无处不在。该死的,我想念 SQL。
    猜你喜欢
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 2023-03-08
    • 2011-08-23
    • 2019-02-06
    • 2020-03-21
    • 1970-01-01
    • 2016-06-28
    相关资源
    最近更新 更多