Reputation: 1274
Using the latest Spring Data Mongo (2.1.1 at time of writing), how do I specify to get the first record of a "custom" query method? Here is an example:
@Query(value="{name: ?0, approval: {'$ne': null}}",
sort="{'approval.approvedDate': -1}",
fields = "{ _id: 1 }")
List<Item> getLatestApprovedIdByName(String name, Pageable pageable);
/**
* Finds the id of the most recently approved document with the given name.
*/
default Item getLatestApprovedIdByName(String name) {
return getLatestApprovedIdByName(name, PageRequest.of(0, 1)).stream()
.findFirst()
.orElse(null);
}
Ideally I could just annotate getLatestApprvedIdByName taking only the String
parameter.
There doesn't seem to be a limit field on the org.springframework.data.mongodb.repository.Query
annotation.
It seems odd because I can emulate everything the named methods do except findFirst
.
Without the Pageable
, I get IncorrectResultSizeDataAccessException
, and returning a List
is not acceptable because I don't want to waste time returning an arbitrarily large result, plus the complicated code needing to deal with the possibility of 0 or 1 items.
Upvotes: 8
Views: 21869
Reputation: 1574
as I had the same issue; I did find @Aggregation a more useful and cleaner solution you can do this:
@Aggregation({
"{$match: { name: ?0, approval: {$ne: null} }",
"{$sort: { _id: 1 } }",
"{$limit: 1 }"
})
Optional<Item> getLatestApprovedIdByName(String name);
Upvotes: 2
Reputation: 3777
Because your query returns multiple documents, there's no way to make it return a single Item
directly.
Stream
// Repository
@Query(value="{name: ?0, approval: {'$ne': null}}",
sort="{'approval.approvedDate': -1}",
fields = "{ _id: 1 }")
Stream<Item> getLatestApprovedIdByName(String name);
// Service
default Item getLatestApprovedIdByName(String name) {
return getLatestApprovedIdByName(name).stream().findFirst().orElse(null);
}
Due to the way Stream
works, you'll only fetch the first query result instead of the entire result set. For more information, please see the documentation.
Page
and Pageable
// Repository
@Query(value = "{name: ?0, approval: {'$ne': null}}", fields = "{ _id: 1 }")
Page<Item> getLatestApprovedIdByName(String name, Pageable pageable);
// Service
default Item getLatestApprovedIdByName(String name) {
PageRequest request = new PageRequest(0, 1, new Sort(Sort.Direction.DESC, "approval.approvedDate"));
return getLatestApprovedIdByName(name, request).getContent().get(0);
}
By making use of PageRequest
, you can specify how many results you want as well as specify the sort order. Based on this answer.
Upvotes: 11