The JsonPipeline Class with Pipleline Builder
In our Mongo package we add the following subclass:
public class Mongo { ... public static class JsonPipeline { private static String trailingBracketWithSpaces = "\\]\\s*$"; private static String startBracketWithSpaces = "^\\s*\\["; private String totalPipelineString = ""; public List<BsonDocument> get() { return parseJsonPipline(); } private List<BsonDocument> parseJsonPipline() { this.add("[{$addFields: {oid: {$toString: \"$_id\"}}}, {$unset: \"_id\"}]"); var pipelines_ = new BsonArrayCodec() .decode(new JsonReader(totalPipelineString), DecoderContext.builder().build()) .stream() .map(BsonValue::asDocument) .collect(Collectors.toList()); return pipelines_; } public JsonPipeline add(String json) { if (totalPipelineString.isEmpty()) { totalPipelineString = json; } else { String prevRemoveCloseBrac = totalPipelineString.replaceAll(trailingBracketWithSpaces, ""); String nextRemoveOpenBrac = json.replaceAll(startBracketWithSpaces, ""); totalPipelineString = prevRemoveCloseBrac + "," + nextRemoveOpenBrac; } return this; } public String getTotalPipelineString() { return totalPipelineString; } /** * oid will be automatically created for foreign collection, the result will * always be an array. * Make sure to {$unwind: "$newFieldName"} if you are sure there are only one * element in the result. */ public JsonPipeline addLeftJoin( String foreignCollection, String localField, String foreignField, String leftJoinPipeline, String newFieldName) { String _jsonPipeline = String.format(""" [ { $addFields: { tmp_localfield: "%s" } }, { $unwind: { path: "$tmp_localfield", preserveNullAndEmptyArrays: true } }, { $lookup: { let: { tmp: "$tmp_localfield"}, from: "%s", pipeline: [ { $addFields:{ oid: {$toString: "$_id"} } }, { $unset: "_id" }, { $match:{ $expr:{ $eq: ["$$tmp", "%s"] } } }, %s ], as: "tmp_singleElementList" } }, { $unwind: { path: "$tmp_singleElementList", preserveNullAndEmptyArrays: true } }, { $group:{ _id: "$_id", originalData: { $first: "$$ROOT"}, pushList: { $push: "$tmp_singleElementList" } } }, { $replaceRoot: { newRoot: { $mergeObjects: [ "$originalData", { %s: "$pushList" } ] } } }, { $unset : "tmp_singleElementList" }, { $unset : "tmp_localfield" } ] """, "$" + localField, foreignCollection, "$" + foreignField, leftJoinPipeline.replaceAll("(^\\s*\\[)|(\\]\\s*)$", ""), newFieldName); return this.add(_jsonPipeline); } } public static JsonPipeline createJsonPipeline() { return new JsonPipeline(); } }
Pipelines
Simplest One
Now a projection pipeline can be as simple as
var pipeline = Mongo.createJsonPipeline(); pipeline.add("[{ $project: { code: 1, name: 1, role: 1 }}]"); List<Document> results = companies.aggregate(pipeline.get()).into(new ArrayList<>());
instead of
var projections = Arrays.asList( Aggregates.project( Projections.fields( Projections.include("code"), Projections.include("name"), Projections.include("role") )) ); List<Document> results = companies.aggregate(projections).into(new ArrayList<>());
More Advanced Pipeline with Left Joins
var chainOid = searchEmailRefinedParam.getEmail_chain_oid(); var chainCollection = mongodb.getCollection(CollectionNames.email_messages); var pipeline = MongoDB.createJsonPipeline(); pipeline .add(String.format("[{ $match:{ email_chain_oid: \"%s\" }}]", chainOid)) .addLeftJoin(CollectionNames.users, "sender_email", "user_name", "[{ $project: {user_name: 1, email: 1, first_name: 1, last_name: 1, company_code: 1} }]", "senderInDb") .add("[{$unwind: \"$senderInDb\"}]") .addLeftJoin(CollectionNames.users, "recipient_emails", "user_name", "[{ $project: {user_name: 1, email: 1, first_name: 1, last_name: 1} }]", "recipientsInDb") .addLeftJoin(CollectionNames.companies, "senderInDb.company_code", "code", "[{ $project:{ name:1 } }]", "sender_company") .add("[{ $unwind: \"$sender_company\" }]"); var emailsResult = chainCollection.aggregate(pipeline.get()).into(new ArrayList<>());