Search code examples
mongodbmongodb-queryaggregation-frameworkmongodb-java

Java MongoDB Projection


I am referring mongodb official page for projection where I came across following example where elements of array in subdocument is filtered: https://docs.mongodb.com/manual/reference/operator/aggregation/filter/#exp._S_filter

db.sales.aggregate([
   {
      $project: {
         items: {
            $filter: {
               input: "$items",
               as: "item",
               cond: { $gte: [ "$$item.price", 100 ] }
            }
         }
      }
   }
])

I am trying to implement this in Java but I am not doing it correctly and elements in subdocument array are not filtered.

Input Collection:

{
   _id: 0,
   items: [
     { item_id: 43, quantity: 2, price: 10 },
     { item_id: 2, quantity: 1, price: 240 }
   ]
}
{
   _id: 1,
   items: [
     { item_id: 23, quantity: 3, price: 110 },
     { item_id: 103, quantity: 4, price: 5 },
     { item_id: 38, quantity: 1, price: 300 }
   ]
}
{
    _id: 2,
    items: [
       { item_id: 4, quantity: 1, price: 23 }
    ]
}

Expected Output Collection:

{
   "_id" : 0,
   "items" : [
      { "item_id" : 2, "quantity" : 1, "price" : 240 }
   ]
}
{
   "_id" : 1,
   "items" : [
      { "item_id" : 23, "quantity" : 3, "price" : 110 },
      { "item_id" : 38, "quantity" : 1, "price" : 300 }
   ]
}
{ "_id" : 2, "items" : [ ] }

In Java(mongo Driver 3.9.1), this is what I am doing:

Bson priceFilter = Filters.gte("items.price", 100);
mongoCollection.aggregate(
  Aggregates.project(Projections.fields(priceFilter))
);

How do I project with aggregate function for the subdocument arrays where I need to filter out elements from subdocument array based on some condition?


Solution

  • In MongoDB Java Driver 3.9.1, collection.aggregate() takes a java.util.List as parameter. So you need to replace your Java code with the below.

    mongoCollection.aggregate(
      Arrays.asList(
        Aggregates.project(Projections.computed("items",
          new Document().append("$filter",
            new Document().append("input", "$items").append("as", "item").append("cond", 
            new Document().append("$gte", Arrays.asList("$$item.price",100))))))
        )
    );