0

In a spring-boot data mongodb application I whould like to return the last element of an embeded collection.

My document is :

@Document
public class ConnectedObject {
  @Id
  private String uuid;
  private List<Measure> measures = new ArrayList<>();
}

public class Measure {
  private LocalDateTime timestamp;
  private long stepsCount;
}

Exemple of data in mongoDb:

{
 "_id":"aaaa",
 "measures":[
   {"timestamp":"2018-04-05T08:20:33.561Z","stepsCount":"0"},
   {"timestamp":"2018-04-05T08:21:35.561Z","stepsCount":"10"},
   {"timestamp":"2018-04-05T08:20:35.561Z","stepsCount":"0"}
  ]
 }

I whould like to get the last measure (filter by timestamp field) of the connectedObject (filter onthe uuid). I don't know how to write the query using MongoTemplate.

I already have custom repository in the project.

BokC
  • 333
  • 5
  • 19

2 Answers2

0

Something like the query below should give what you need

db.collection.aggregate([
 {$match: {'$uuid':'12345'}},
 {$sort:{'$measure.timestamp':1}},
 {$project:{
     uuid: 1,
     last: { $arrayElemAt: [ "$measures", -1 ] }
  }
 }
])
Graciano
  • 508
  • 4
  • 11
  • It's not ok. The "$sort" have no action on the "measures" list. Is it possible to sort the "$measures" éléments on the $arrayElemAt ? – BokC Apr 05 '18 at 14:07
0

After a lot of try, the one running is :

public Measure getLastMeasureOf(String uuid) {
    final Aggregation agg = newAggregation(
            match(Criteria.where("uuid").is(uuid)),
            unwind("measures"),
            sort(Sort.Direction.DESC, "measures.timestamp"),
            group("uuid").first("$$ROOT").as("result"),
            project("result.uuid").and("result.measures").as("last")
    );

    final AggregationResults<ObjectWithLastMeasure> results
            = template.aggregate(agg, ConnectedObject.class, ObjectWithLastMeasure.class);

    final ObjectWithLastMeasure owlm = results.getUniqueMappedResult();
    return owlm == null ? null : owlm.getLast();
}
BokC
  • 333
  • 5
  • 19