0

I am trying to fetch an element from an array in the MongoDB in my Spring Framework project.

I have find the solution for MongoDB shell, but I do not know how to implement it by Spring.data.core.aggregation, one of aggregation operator @addFields is not supported by Spring.

Could anyone tell me how to replace this @addField or how to implement in it another way? Thank you so much!!!

MongoDB sample data:

{
    "_id" : 15,
    "items" : [
            {
                    "columns" : [
                            {
                                    "title" : "hhh",
                                    "value" : 10
                            },
                            {
                                    "title" : "hahaha",
                                    "value" : 20
                            }
                    ]
            },
            {
                    "columns" : [
                            {
                                    "title" : "hiii",
                                    "value" : 50
                            }
                    ]
            }
    ]
}

Expected result:

{
"_id" : 15,
"items" : [
        {
                "columns" : [
                        {
                                "title" : "hahaha",
                                "value" : 20
                        }
                ]
        },
        {
                "columns" : []
        }
]

}

The solution for MongoDB Shell:

let value = "hahaha";

db.coll.aggregate([
    {
        "$addFields": { 
            "items": { 
                "$map": { 
                    "input": "$items", 
                    "as": "item", 
                    "in": { 
                        "columns": { 
                            "$filter": { 
                                "input": "$$item.columns", 
                                "as": "elt", 
                                "cond": { "$eq": [ "$$elt.title", value ] } 
                            } 
                        }
                    }
                } 
            } 
        } 
    } 
])

MongoDB version: 3.4.1
Spring version: 1.4.3

1 Answer 1

2

You can try the following but you'll need to use 1.8.5 version.

Aggregation aggregation = newAggregation(
            project("_id").and(new AggregationExpression() {
                @Override
                public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
                    DBObject filter = new BasicDBObject("input", "$$item.columns").append("as", "elt").append("cond",
                            new BasicDBObject("$eq", Arrays.<Object>asList("$$elt.title", "hahaha")));
                    DBObject map = new BasicDBObject("input", "$items").append("as", "item").append("in", filter);
                    return new BasicDBObject("$map", map);
                }
            }).as("items")
  );

The support for some of Mongo3.2 aggregation operators were added in 1.10.0.RC1. If you are okay with updating to release candidate version you can use the below version. I couldn't find $addFields stage in the RC so kept the $project stage.

Aggregation aggregation = newAggregation(
            project("_id")
                    .and(mapItemsOf("items").as("item").andApply(filter("item.columns")
                            .as("elt")
                            .by(valueOf("elt.title").equalToValue("hahaha"))
                    )).as("items")
);

Static Imports:

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.aggregation.ArrayOperators.Filter.filter;
import static org.springframework.data.mongodb.core.aggregation.ComparisonOperators.Eq.valueOf;
import static org.springframework.data.mongodb.core.aggregation.VariableOperators.mapItemsOf;
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your suggestion, but changing the version is too complex for me.
Spring boot 1.4.3 has spring mongo db 1.9.6 version. So first option should work for you. Did you try ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.