1
votes

Let's say I have a collection items and these are the data in this collection:

{ 
  "_id": 1
  "tags": ["handbag", "women", "leather"]
  "price": 30
}, {
  "_id": 2
  "tags": ["jewelry", "women", "necklace"]
  "price": 40
}, {
  "_id": 3
  "tags": ["men", "leather", "necklace"] 
  "price": 10
}

With the java model

class Item {
  public ObjectId id;
  public List<String> tags;
  public int price;
}

How do I get the average price of the items that are tagged with leather?

I know that from mongodb cli I can get this with:

db.items.aggregate([
  { $match: { tags: { $in: ["leather"] } } }, 
  { $group: { _id: null, averagePrice: { $avg: "$price" } } }
])

But how can I convert this into java spring boot/data code? The Aggregation.group() method is accepting only the name of the field I cannot specify _id: null so it would group all the matching elements as one group.

Here is the aggregation query in Java

Aggregation.newAggregation(
   match(Criteria.where("tags").in("leather")),
   group("_id") // how to group all matching rows in one group.
               .avg("price").as("averagePrice")
);
1
what is your equivalent java model for the document? - Naman
Updated the question with the model. - danial
Try Aggregation agg = Aggregation.newAggregation( match(Criteria.where("tags").in("leather")), group().avg("price").as("averagePrice") ); - s7vr
Ah. Thanks, that works great. I knew it's an easy solution that I just don't see. Could you submit an answer so I mark it? - danial
For others of you that have landed here -- evidently this is not the case for mongo-java-driver-3.8.2 -- Aggregation is no longer a class listed there, nor in the 3.6 API documentation index. And this is only a little over a year old. - arcy

1 Answers

0
votes

In java, the relevant code should be somewhat like :

collection.aggregate(
    Arrays.asList(
        Aggregates.match(Filters.eq("tags", "leather")),
        Aggregates.group("$price", Accumulators.avg("$price", "averagePrice"))
    )
)