Spring data mongoRepository Query sort - java

I was looking to see how I could introduce a sort into a Query annotation in a repository method that I have.
I already saw this code in Google and here, but I could not make it works
#Query("find({state:'ACTIVE'}).sort({created:-1}).limit(1)")
Job findOneActiveOldest();
#Query("{ state:'ACTIVE', $orderby: {created:-1}, $limit:1 }")
Job findOneActiveOldest();
I know that with pagination I can make it, but in some cases I don't need paginate, so I was wondering how to make it with Query annotation.
Any suggestion please?

I don't think it is possible to do it with #Query annotation. If you dont need to paginate you can just make your repository method use Sort parameter:
#Query("{ state:'ACTIVE' }")
Job findOneActive(Sort sort);
and use it:
yourRepository.findOneActive(new Sort(Sort.Direction.DESC, "created"))

Just use sort parameter of #Query annotation. 1 = ASC, -1 = DESC
#Query(
value = ...,
sort = "{'details.requestTime': -1}"
)

if you also want to have pagination then use Pageable as method argument instead of Sort. Try below code:
#Query("{ state:'ACTIVE' }")
Job findOneActive(Pageable pageable);
yourRepository.findOneActive(new PageRequest(0, 1, new Sort(Sort.Direction.DESC,"created")));

Related

use top with list of parameters

I have this spring data repository method
public FileActivity findTopByFileIDOrderByCreatedDesc(String fileID);
This works fine . But how do I make it work for list of parameters ?
This doesn't work (I can have many FileActivity for file id - but I want only the last one) :
public List<FileActivity> findTopByFileIDOrderByCreatedDesc(List<String> fileIDs);
Spring Data's support for derived queries is useful but for anything other than simple queries it is probably easier and clearer just to define your own JPQL query.
#Query("select f from File f where f.id in :fileIds order by f.created desc")
public Page<FileActivity> findTopFilesById(
#Param("fileIDs") List<String> fileIDs, Pageable pageable);
As JPQL does not have a limit keyword you can simply pass in a Page.
List<String> fileIds = //;
Page<File> page = repository.findTopFilesById(fileIds, new PageRequest(0, fileIds.size());
List<File> files = page.getContent();
You could also dynamically specify the sort order in the PageRequest rather than in the JPQL giving a bit more flexibility:
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html
public FileActivity findTopByFileIDInOrderByCreatedDesc(Collection<String> fileIDs);
See more examples here
Note - if you use 'Top' then you get only one record. To get more than one record you have to add a number to 'Top' for example: 'Top10'.
More info here

Spring Data: limit result for custom query

In my Spring Data repository I (have to) use custom queries using the #Query annotation. I know I can limit the number of results in a named query like that
Iterable<Person> findFirst5OrderByLastName()
or that it is possible to limit the number of results by passing a pageable like that
Iterable<Person> findByLastName(String lastName, Pageable pageable)
But is it possible to achieve the same when using a custom #Query annotation?
TIA
EDIT
as I see my question is a little confusing, some clearification:
What I want is to limit the number of the results I get, when using a custom query, so that I neither
1) need to specify the result-size through a pageable
2) need to use a named query to specify the result-size
In fact I want the limitation of the number of results to be completely transparent when invoking method (hence not passing a Pageable) and to not rely on the naming-scheme of Spring Data (as the meaning/function of the method is best conveyed through a custom name)
You can try this:
#Entity
#Table(name = "persons")
public class Person {
//...
}
#Query(value = "select * from persons limit 50", nativeQuery = true)
List<Person> getFirst50();
Don't forget to check whether your SQL server supports the limit keyword.
Of course you can use #Query to order a result, it is an JPQL query e.g.
#Query("SELECT u FROM User u ORDER BY u.name ASC")
Further sorting can be done be either providing a PageRequest or using Sort directly.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.sorting
I would suggest to add "By" but without parameter, it would work:
List<Person> findTop100By();
You need to extend PagingAndSortingRepository
and add method
Page<Person> listAllByPage(Pageable pageable)
See the example
Hello you can try this
#Query("...")
List<YourDTO>getData(Pageable pageable)
In your serviceImpl
List<YourDTO> getData(){
int limit=10;
Pageable pageable = PageRequest.of(0, limit);
return this.repo.getData(pageable);
}
You should avoid nativeQuery

Spring java MongoDB #Query annotation for order top or first records

I use #Query annotation and crudRepository to fetch data from MongoDB.
Example:
#Query("{$query: id: ?0}, $orderby: {dateTime: -1}}")
public List<A> findId(
Integer id, Pageable pageable
);
What do I need to add to my #Query notation if i want to fetch only first N records of collection, or only top N records of collection? I would like to use dynamic query and dynamic set limit and order (first or top records).
you can append your #Query with $limit : 10, or rename your method like : find First10ByDateDesc()
Use the variable sort of the #Query:
#Query(value = "{}", sort = "{ _id : -1 }")
As an example for "order by id desc".

Fetching only first/last element using Spring Data JPA and #Query annotation

EDIT: Solutions to this problem are provided in the second and fourth answer regarding this question setMaxResults for Spring-Data-JPA annotation?
Goal: Fetch the largest/smallest element by property z using a Spring Data JPA repository and the Spring Query annotation.
What I have so far
#Query("SELECT xelement FROM x xelement ORDER BY xelement.z")
public List<X> findFirstElement();
Problem: This query fetches all elements (which is not really effective). If I would use the EntityManager direcly, I could set the number of results using
entityManager.setMaxResults(1)
to only get the first element.
Question: How do I specify the maximum number of results using the #Query annotation?
Idea: Is using a PageRequest of size 0 the way to go?
Constraints: I am aware of the "FindFirstBy...." query feature but I want/have to use the #Query annotation.
You can use the limit property of sql just by adding nativeQuery to #Query annotation. However, there is another and a better way of doing this. Pageable class in your repository method will solve your problem without touching your #Query annotation:
#Query(value = "SELECT xelement FROM x xelement ORDER BY xelement.z")
List<X> findFirstElement(Pageable limit);
To set the limit and offset, use should call this repository method as follows:
List<X> xValues = xRepository.findFirstElement(new PageRequest(0, 1));
Here 1 corresponds to the limit which you want.
UPDATE (SPRING DATA 2.0)
Use PageRequest.of(0, 1) instead of new PageRequest(0, 1)
The closest JPA query syntax I can think for your use case is findFirstByZIsNotNullOrderByZAsc. This should eliminate the need to write custom native query.
Try to do this:
#Query(value = "SELECT xelement FROM x xelement ORDER BY xelement.z LIMIT 1",
nativeQuery = true)

Spring Data JPA QueryDslPredicateExecutor find distinct results

I have a Spring Data & JPA QueryDSL based project in which I have many repository interfaces extending QueryDslPredicateExecutor like below:
public interface ProductRepository extends JpaRepository<Product, Long>,
QueryDslPredicateExecutor<Product> {
}
I am performing findAll() queries with BooleanExpressions all over my application to fetch data. However I now need to find the distinct results of a query based on a particular column.
I am also using Projections & Custom repositories in some cases to select particular columns based on this post.
Is there a way to select distinct so that I only get the distinct values of a particular column for a query, based on any of the above approaches?
Today I've encountered the same issue and it seems that there's no direct repository approach to solve it.
I ended using Querydsl in order to accomplish what I wanted: being able to use Page<T> findAll(Predicate var1, Pageable var2); using distinct.
A simple snippet:
public Page<LocalizedMessage> findAll(Predicate predicate, Pageable pageable) {
QMessage qMessage = QMessage.message;
Querydsl querydsl = new Querydsl(entityManager, new PathBuilder<>(Message.class, qMessage.getMetadata()));
JPAQuery countQuery = querydsl.createQuery(qMessage).distinct().where(predicate);
JPAQuery query = querydsl.createQuery(qMessage).distinct().where(predicate);
querydsl.applyPagination(pageable, query);
return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount);
}
This code is based on QuerydslJpaRepository's findAll(Predicate, Pageable) method. I presumed that it could be easy to extend this repository in order to add findAllDistinct methods using JPQLQuery.distinct().
I've filed a feature request at spring-data's JIRA.
Hope this helps someone.
If you use Querydsl queries directly in your repository you can call query.distinct() to get distinct results.

Categories

Resources