【问题标题】:Filter deeply nested list using Aggregation operations Spring data使用聚合操作过滤深度嵌套列表 Spring 数据
【发布时间】:2023-03-28 10:05:01
【问题描述】:

我有以下文件

[ {
        "pageName": "Content_2",
        "domain": "bingo.com",
        "locale": "en-us",
        "contents": [
            {
                "contentName": "Template_2",
                "fields": [
                    {
                        "title": "Company Name"                     
                    },
                    {
                        "title": "Designation"
                    }
                ]
            }
        ]
    },
{
        "version": 2,
        "pageName": "Content_3",
        "domain": "bingo.com",
        "locale": "en-in",
        "contents": [
            {
                "contentName": "Template_2",
                "fields": [
                    {
                        "title": "Company Name"                          
                    },
                    {
                        "title": "Designation"
                    }
                ]
            }
        ]
    }]

我正在根据域、区域设置和内容名称过滤数据。到目前为止,一切正常。现在,在 fields 数组中,我只想显示那些标题与特定值匹配的字段。我无法弄清楚如何通过聚合操作来做到这一点。我在sn-p下面试过了:

Aggregation aggregation = newAggregation(
                    match(
                        where("domain").is(domain)
                        .and("contents.contentName").is(templateName)
                        .and("locale").in(criteria.getLocales())), 
                        project().and(new AggregationExpression() {
                        @Override
                        public Document toDocument(AggregationOperationContext aggregationOperationContext) {
                            DBObject filterExpression = new BasicDBObject();
                            filterExpression.put("input", "$contents.fields");
                            filterExpression.put("as", "field");
                            filterExpression.put("cond",
                                    new BasicDBObject("$eq", Arrays.<Object>asList("$$field.title", "Company Name")));
                            return new Document("$filter", filterExpression);
                        }

                }).as("field"));
AggregationResults<MyClass> list = mongoOperations.aggregate(aggregation, MyClass.class,
                MyClass.class);

它将所有属性都返回为空。请指导。我是 MongoDB 的新手。提前致谢;

【问题讨论】:

    标签: mongodb spring-boot spring-data aggregation-framework mongotemplate


    【解决方案1】:

    你可以使用这个Aggregation

    db.collection.aggregate([
            { $unwind: '$contents' },
            { $match: { "locale": "en-us", 
    "domain": "bingo.com", "contents.contentName": "Template_2"} },
            { $unwind: '$contents.fields' },
            { $match: { 'contents.fields.title' : "Company Name" } },
            { $group: { _id: '$_id', 
                  fields: { $push: { title: '$contents.fields.title'}}, 
                  "locale" : {$first: "$locale"},
                  "domain" : {$first: "$domain"},
                  "pageName" : {$first: "$pageName"},
                  'contentName': {$first: '$contents.contentName'}
                  }
            },
            { $group: { _id: '$_id', 
             "locale" : {$first: "$locale"},
             "domain" : {$first: "$domain"},
             "pageName" : {$first: "$pageName"},
             contents: { $push: { "contentName": '$contentName', "fields": '$fields' }}, 
            }}
        ])
    

    或者简单地应用这个。我的道歉如果我在语法上犯了错误,但尽我所能把它们改正

    Aggregation aggregation = newAggregation(
                        unwind("contents),
                        match(
                             where("$domain").is(domain)
                            .and("$contents.contentName").is(templateName)
                            .and("$locale").in(criteria.getLocales())
                           ),
                        unwind("$contents.fields"),
                        match(where("$contents.fields.title").is(title)),
                        group("_id")
                         .push("$contents.fields.title").as("fields")
                         .push("$locale").as("locale")
                         .push("$domain").as("domain")
                         .push("$pageName").as("pageName")
                         .push("$contents.contentName").as("contentName"),
                     group("_id")
                     .push("locale").as("locale")
                     .push("domain").as("domain")
                     .push("pageName").as("pageName")
                     .push(new BasicDBObject
                       ("contentName", "$contentName").append
                       ("fields", "$fields").as("contents"))
                    );
    AggregationResults<MyClass> list = mongoOperations.aggregate(aggregation, MyClass.class,
                    MyClass.class);
    

    运行它,你的结果在等着你...

    【讨论】:

    • 谢谢伙计。我会试试看。唯一困扰我的是再次推送属性,因为还有许多其他领域我没有展示,只是提出了问题。我尝试了这种放松方法,但代码变得混乱。我希望有一些简短的内容。
    • 嘿,使用它并让 Idea 更简短:- db.locations.aggregate([{$unwind:'$contents'},{$match:{"locale":"en- us","domain":"bingo.com","contents.contentName":"Template_2"}},{$unwind:'$contents.fields'},{$match:{'contents.fields.title': "公司名称"}},{$group:{_id:'$_id',fields:{$push:{title:'$contents.fields.title'}},"root":{$first:"$$ ROOT"}}},{$group:{_id:'$_id',root:{$first:'$root'},contents:{$push:{"contentName":'$contentName',"fields": '$fields'}},}},{$replaceRoot:{newRoot:{$mergeObjects:["$root",{contents:'$contents'}]}}}])
    猜你喜欢
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 2018-11-17
    • 2018-01-30
    • 2014-12-31
    • 1970-01-01
    相关资源
    最近更新 更多