11

I have found several example at StackOverFlow related to addFields in Aggregation. But no one implemented in Java.

db.getCollection('myDocument').aggregate([
    {$match : {"metaId.ref.uuid" : "d6112808-1ce1-4545-bd52-cf55bc4ed25e"}},
    {$lookup: {
        from: "simple",
        localField: "someId.ref.uuid",
        foreignField: "uuid", 
        as: "simple"}},
    {"$unwind": "$simple"},
    {"$addFields": { "metaId.ref.name" : "$simple.name" }}
])

I am not able to Implement In Java Correctly:-- Not getting proper procedure

LookupOperation lookupOperation = LookupOperation.newLookup()
    .from("simple")
    .localField("execId.ref.uuid")
    .foreignField("uuid")
    .as("simple");
Aggregation myDocAggr = new Aggregation(
    match(Criteria.where("metaId.ref.uuid").is(someUUID)), 
    group("uuid").max("version").as("version"),
    lookupOperation,
    Aggregates.unwind(""),
    Aggregates.addFields(fields));
Document document = new Document();
AggregationResults<String> myDocAggrResults =
    mongoTemplate.aggregate(myDocAggr, myDocument, myDocument.class);
List<String> mydocumentList = myDocAggrResults .getMappedResults();

Not able to use unwind and addFields, this is sample java code, but it is not ok. Please help me. Thanks in advance

8
  • which error/stacktrace? Commented Nov 12, 2018 at 11:54
  • what is the compilation error saying? Commented Nov 12, 2018 at 11:58
  • I guess there is at least a closing bracket missing Commented Nov 12, 2018 at 11:59
  • After Aggregates.unwind(""), there should be some closing brackets? what arguments are you trying to give to the method call? Commented Nov 12, 2018 at 12:00
  • Which newAggregation method do you try to invoke? Commented Nov 12, 2018 at 12:02

3 Answers 3

18

You are mixing the java driver Aggregates method with Spring Aggregation methods.

Also $addFields is still not supported in spring mongo.

You have to use below aggregation.

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
Aggregation myDocAggr = newAggregation(
       match(Criteria.where("metaId.ref.uuid").is(someUUID)), 
       group("uuid").max("version").as("version"),
       lookup("simple","execId.ref.uuid","uuid","simple"),
       unwind("simple"),
       new AggregationOperation(){ 
         @Override 
         public Document toDocument(AggregationOperationContext aoc) {
            return new Document("$addFields",new Document("metaId.ref.name","$simple.name"));
         }
      }
)
List<Document> mydocumentList=mongoTemplate.aggregate(myDocAggr,"myDocument",Document.class).getMappedResults();
Sign up to request clarification or add additional context in comments.

6 Comments

which version of spring you are using for this code snippet, I am not able to add unwind and lookup in mine code.
Thanks for providing a solution :-) Although unwind did not work for me, but I got a way to implement it.
You are welcome. Use import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;. It has all the aggregation operators.
I have constraints, cannot use monogo_spring_data greater than 1.90 so I have switched to mongo java driver, because I have huge records, want to use the cursor, Please let me know how can I add fields, using java.
Don't mix & match spring aggregation with java driver aggregation. Something like Aggregates.addFields(new Field("metaId.ref.name", "$simple.name")) should work for java driver. Convert rest of the aggregation operators to use java driver.
|
7

Since version 3.0 of 'spring-data-mongodb' it is actually possible to create a AddField aggration very easily. You can use the AddFieldsOperationBuilder.

In the example below I add a string id field for the objectId field named _id. The string field idString can get used in a lookup aggregation.

Example:

    AddFieldsOperation addFieldsOperation = Aggregation.addFields().addFieldWithValue("idString", ConvertOperators.ToString.toString("$_id")).build();

1 Comment

Do you happen to know how to add values of two other field and put as the value for the new field?
4

Although the $addFields are not supported by spring mongo you can implement it by yourself:

import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.*;
import java.util.LinkedHashMap;
import java.util.Map;

public class AddFieldsOperation implements FieldsExposingAggregationOperation {
    private Map<String, Object> fields = new LinkedHashMap<>();

    public AddFieldsOperation(String field, AggregationExpression expression) {
        addField(field, expression);
    }

    public AddFieldsOperation addField(String field, AggregationExpression expression) {
        this.fields.put(field, expression.toDocument(Aggregation.DEFAULT_CONTEXT));
        return this;
    }

    @Override
    public Document toDocument(AggregationOperationContext context) {
        Document doc = new Document();
        fields.forEach(doc::append);
        return new Document("$addFields", doc);
    }

    @Override
    public boolean inheritsFields() {
        return true;
    }

    @Override
    public ExposedFields getFields() {
        final String[] fieldsArray = fields.keySet().toArray(new String[0]);
        return ExposedFields.synthetic(Fields.fields(fieldsArray));
    }

And use it like this:

...
ArithmeticOperators.Add value1 = ArithmeticOperators.Add.valueOf(0);
ArithmeticOperators.Add value2 = ArithmeticOperators.Add.valueOf(0);
AddFieldsOperation addFields
            = new AddFieldsOperation("value1", value1)
            .addField("value2", value2);
pipeline.add(addFields);
...
Add value1PlusValue2 = Add.valueOf("$value1").add("$value2");
...

Hope it will help someone.

Comments

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.