How to sort huge data in spring data mongodb - sorting

I have a collection that contains lots of document(about 10 million).How can i sort these documents without using aggregation framework ?
Here i want to use like this code :
Pageable pageable = new PageRequest(pageNumber, howMany, sort);
query.with(pageable);

Related

Spring boot JPA Specification API with Pagination and Sorting

Im trying to implement a search in spring boot. Since the search params is dynamic, i had to go for specification api. My requirement is to search for orders given certain params and sort those orders by creation date. Since data can be large, the api should also support for pagination.
Below is the code snipped of the predicates.
public search(OrderSearchCriteria searchCriteria, Integer pageNo, Integer pageSize) {
Pageable pageRequest = (!ObjectUtils.isEmpty(pageNo) && !ObjectUtils.isEmpty(pageSize))
? PageRequest.of(pageNo, pageSize)
: Pageable.unpaged();
Page<Order> ordersPage = this.dao.findAll(((Specification<Order>)(root, query, criteriaBuilder) -> {
// my search params, its more than what is shown here
Long id = searchCriteria.getId();
Priority priority = searchCriteria.getPriority();
List<Predicate> predicates = new ArrayList<>();
if(!ObjectUtils.isEmpty(id))
predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("id"), id)));
if(!ObjectUtils.isEmpty(priority))
predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("priority"), priority)));
// This line is causing the issue
query.orderBy(criteriaBuilder.desc(root.get("creationDate")));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
}), pageRequest);
The issue is, if i add this sort by line query.orderBy(criteriaBuilder.desc(root.get("creationDate")))
Pagination is not working. page 0 and page 1 both shows same result(same order) given size as 1. But page 2 shows different result as expected. But if i remove the sort by line shown above, the code is working as expected. How do i support both pagination and sorting without having these issues? i tried applying sort in pagerequest as well. But same issue PageRequest.of(pageNo, size, sort.by(DESC, "creationDate")). Appreciate help.
What do you mean by "it shows same result"? There might be multiple entries that have the same creation date and if you omit a sort, Spring Data will by default sort by id to provide a consistent result.

Spring Data JPA: Retrieve page with N-1 objects without touching DB several times using Pageable

Using a JpaRepository in Spring Boot 2.3.5 and Java 11, I'm trying to retrieve a Page of movies and their corresponding genres (one Movie has only one Genre: it's a N-1 association):
#Query("SELECT obj FROM Movie obj WHERE :genre IS NULL OR obj.genre = :genre")
Page<Movie> find(Genre genre, Pageable pageable);
However, when genre is null (scenario where all genres must be considered), my show-sql logs are showing that JPA is touching DB again and again for each different genre.
Furthermore, surprisingly, if I simply call the built-in findAll method, JPA is also touching DB for each different genre:
Page<Movie> result = movieRepository.findAll(Pageable pageable);
A native query should work around, but I'd like to use my Pageable object. So how could I retrieve a page with N-1 objects without touching DB several times using Pageable?

How to get list of a field value as the result in mongodb with Spring Data

I want to get a list of a field's value from documents.
How can I write the following in spring
db.collection.find({"name" : "tom"}).map(function(u) return u.age)
If I use
Aggregation.match(Criteria.where("name).in("tom))
Aggregation.group("age")
I get list Objects with {_id, age} but I want List<String> ages
First things first, You don't need to map to get just the age field from the collection, you can just use projection.
Projection returns _id by default, so, you might want to specify it to be not returned if that's so.
i.e db.collection.find({}, {'age': 1, '_id': 0})
In Spring Data, you can perform a similar operation with include() and exclude().
i.e
Query query = new Query();
query.fields().include("age").exclude("id");
List<User> usersWithJustAgeInformation = mongoTemplate.find(query, User.class);
but this will also return an object of type User from which you can very easily filter the List <String> ages with stream, map and collect.
Eg.
Query query = new Query();
query.fields().include("age").exclude("id");
List<String> ages = mongoTemplate.find(query, User.class).stream().map(User::getAge).collect(Collectors.toList());
Please read https://www.baeldung.com/spring-data-mongodb-projections-aggregations for more information and examples of projection and aggregation.

How to do Rescore with Spring Data Elastic search?

I'm using spring boot with the Spring Data Elastic search client.
And I have something like
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
QueryBuilder nameQuery = boolQuery().should(matchQuery("fullName", queryText)).boost(10)
.should(matchQuery("fullName", queryText).fuzziness(Fuzziness.ONE)).boost(1.5f)
.should(matchQuery("fullName.autocomplete", queryText)).boost(2f)
.should(matchQuery("fullName.metaphone", queryText)).boost(1.2f)
.should(matchQuery("fullName.synonym", queryText)).boost(2)
.should(matchQuery("fullName.porter", queryText));
searchQueryBuilder.withQuery(nameQuery);
List<MasterIndex> masterIndices = masterIndexRepository.search(searchQueryBuilder.build());
After getting all of the names, I'd like to try with rescoring using some other attributes to reorder the result that might be more relevant. I know there is a rescore query, like this
RescoreBuilder.QueryRescorer rescoreBuilder = RescoreBuilder.queryRescorer(boolQuery().should(hasChildQuery("client",
QueryBuilders.boolQuery()
.should(QueryBuilders.termsQuery("enrollments.programId", programId))
))).setQueryWeight(0.7f).setRescoreQueryWeight(0.3f);
But how to put the rescoreBuilder together with NativeSearchQueryBuilder?
Or if there's any other way to customize score and order the result more intelligently, please let me know.

Spring Mongo criteria problems with andOperator

I'm trying to create a dynamic mongoDB query using spring Criteria. My query is :
Criteria.where(key1).is(value1).and(key2).is(value2)
The numbers of key/value is not fixed but can change.
I try to use andOperator but it's not for my case.
Can someone help me?
This post explains a similara problem:
Spring Mongo criteria querying twice the same field
This is what you want to do:
Criteria criteria = new Criteria().andOperator(
Criteria.where("key1").is(value1),
Criteria.where("key2").is(value2));
// to print the mongodb query for debug purposes
// System.out.println(criteria.getCriteriaObject());
// execute with a mongoTemplate
List<YourClass> documents = mongoTemplate.find(new Query(criteria), YourClass.class);

Resources