Search code examples
mongodbmongodb-queryaggregation-frameworkmongodb-java

Optimize set and project operation


An intermediate output of our aggregation pipeline is as follows:

{ "_id" : { "$oid" : "..." }, "requestId" : "REQ4", "scrips" : ["3553", "5647", "1234", "0007"], "matched" : [{ "settlement" : "9001" }, { "settlement" : "9002" }], "settled" : [{ "settlement" : "9001" }, { "settlement" : "9003" }] }
{ "_id" : { "$oid" : "..." }, "requestId" : "REQ5", "scrips" : ["3554", "3456"], "matched" : [{ "settlement" : "9003" }], "settled" : [{ "settlement" : "9001" }, { "settlement" : "9003" }] }

The ask is to print/return request(and scrips) for which matched is an exact subset of settled. Expected output:

{ "requestId" : "REQ5", "scrips" : ["3554", "3456"] }

The following code seems to achieve it - is there a more efficient and concise way to achieve it?

        filters.add(Aggregates.project(
                Projections.fields(
                Projections.include("requestId","scrips"),
                Projections.computed("unmatched", 
                        Document.parse("{ $setDifference: 
                        ['$matched','$settled'] }")))));
        filters.add(Aggregates.match(Document.parse("{unmatched:{$eq:[]}}")));  
        filters.add(Aggregates.project(
                Projections.fields(
                Projections.excludeId(),
                Projections.include("requestId","scrips"))));

Solution

  • We can also do it the following way:

    List<Bson> filters = Arrays.asList(
                    Aggregates.match(
                            Document.parse("{ $expr:{ $eq:[ { $size: { $setDifference:[ '$matched', '$settled' ] } }, 0 ] } }")),
                    Aggregates.project(
                            Projections.fields(Projections.excludeId(), Projections.include("requestId", "scrips"))));