Java MongoTemplate - Adding addFields in Aggregation Operations
Working with mongoTemplate to operate MongoDB is full of pitfalls - the examples in the Spring Boot official documentation don't meet real-world requirements.
Scenario
I have a MongoDB query like this, where the _id from the wallpaper document is associated with wallpaper_id from the wallpaper_get_success document:
db.wallpaper.aggregate([
{
$addFields: {
"_id": {
"$toString": "$_id"
}
}
},
{
"$lookup": {
"from": "wallpaper_get_success",
"localField": "_id",
"foreignField": "wallpaper_id",
"as": "success_id"
}
},
{
"$match": {
"success_id": {
"$ne": []
}
}
},
{
"$sample": {
"size": 5
}
}
])
The following section is essential because of this issue: MongoDB join query - localField using _id for matching doesn't work
{
$addFields: {
"_id": {
"$toString": "$_id"
}
}
}
But while the database operation is straightforward SQL, converting it to Java code is painful. In newAggregation, lookup, match, and sample operations all work, but addFields doesn't:
Aggregation aggregation = newAggregation(
Aggregation.fields(""), // This part is problematic
lookup("wallpaper_get_success", "_id", "wallpaper_id", "success_id"),
match(Criteria.where("success_id").ne(new WallpaperGetSuccess[]{})),
sample(5)
);

There's almost no information online about this operation. I finally found the answer on StackOverflow.
Solution
Original post: How can I implement addFields mongoDB query in Java
The solution is to change addFields to new Document.
Key point: The imported Document class should be from org.bson, not from spring-boot-data-mongo:
import org.bson.Document;
Code:
import org.bson.Document; // Key import
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import org.springframework.data.mongodb.core.query.Collation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Component;
Aggregation aggregation = newAggregation(
aoc -> new Document("$addFields",new Document("_id",new Document("$toString","$_id"))),
lookup("wallpaper_get_success", "_id", "wallpaper_id", "success_id"),
match(Criteria.where("success_id").ne(new WallpaperGetSuccess[]{})),
sample(5)
);
You can also avoid using lambda expressions, like this:

Here's a comparison between the native SQL and Java code:
