Spring Data Query with Array of strings using #Query annotation - java

I'm using a Spring repository to query from MongoDB. I have a function in my repo like the one below which searches for a key-value pair in the DB.
#Query("{ '?0' : { $eq: ?1 } }")
public Page<GsJsonStore> matchJson(String term, String value, Pageable pageable);
I have to modify the query to accept an array of strings like below :
public Page<GsJsonStore> matchJson(String[] term, String[] value, Pageable pageable);
How do I modify the query to search for multiple K-V pairs using an AND/OR condition?
Like :
{'term[1]' : {$eq : value[1]} AND 'term[2]' : {$eq : value[2]} AND.....}
Thanks!

Related

mongodb get the list of id

I have the below user collection
{
"_id":"562e7c594c12942f08fe4192",
"shape":"square",
"color":"blue"
},
{
"_id":"562e7c594c12942f08fe4193",
"shape":"square",
"color":"black"
}
How can i get only the _id attribute with mongodb to get the list of id
With jpa the query is like below
#Query("SELECT u.id FROM User u)
Set<String> findUserIds();
If you are using MongoRepository, you can write it this way:
#Query(value="{}", fields="{_id : 1}")
List<User> findIds();
This will only populate the id field within the user objects, which then can be mapped to a collection of strings.

Difference between Query keywords Containing, IsContaining, Contains, Like in Spring Data JPA

What is the difference between Query keywords Containing, IsContaining, Contains, Like in Spring Data?
List<T> findBy...Containing();
List<T> findBy...Contains();
List<T> findBy...IsContaining();
List<T> findBy...Like();
IsContaining, Containing and Contains are almost same.
For example,
List<Employee> findByNameContaining(String name);
List<Employee> findByNameContains(String name);
List<Employee> findByNameIsContaining(String name);
For all above methods spring data will create query with LIKE clause where value will be wrapped in % as shown in below query when Name = ABC
SELECT * FROM Employee WHERE Name LIKE '%ABC%'
Whereas in Like method user need to explicitly add the wildcards.
For example,
List<T> findByNameLike(String name);
For above method spring data will create query similar to below query when Name = ABC
SELECT * FROM Employee WHERE Name LIKE 'ABC'

In back end (java spring boot) sorting, how to sort with Alias name using pageable? Without parent table as prefix

I am using backend pagination and sorting with java spring boot pageable. While passing sort field as usercount (This gives count of user_role_mapping), Java triggering an error column f.usercount does not exist .
Actually usercount not a column it's an Alias name.
How to sort using usercount as Alies name without f. as prefix?
API URL:
http://localhost:8080/facility/list?pageNumber=0&pageSize=10&sortBy=usercount&sortType=asc
Default sortBy & sortType are id and desc respectively in controller layer.
Java Code give below:
Pageable pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).descending());
if (sortType.equalsIgnoreCase("asc")) {
pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).ascending());
}
Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12,pageable);
Postgres sql Hibernate query for listing facility details along with user count based on role id, given below:
#Query(nativeQuery = true, value = " Select f.name as facilityname,f.id as facilityid,count(urm.id) as usercount
from facility f
join user u on f.user_id=u.id
join user_role_mapping urm on u.id = urm.user_id
where urm.role_id=:roleId ")
Page<FacilityProjection> facilityListing(#Param("roleId") Long roleId,Pageable pageable);
The problem is that usercount is aggregation function result. To order by this field query have to contain order by count(urm.id) instead of order by usercount.
In this case I'd suggest you to resort page content using Collections::sort
boolean sortByUserCount = sortBy.equalsIgnoreCase("usercount");
boolean desc = sortType.equalsIgnoreCase("desc");
final Pageable pageable;
if (sortByUserCount) {
pageable = PageRequest.of(pageNumber, pageSize);
} else {
if (desc) {
pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).descending());
} else {
pageable = PageRequest.of(pageNumber, pageSize, Sort.by(sortBy).ascending());
}
}
Page<FacilityProjection> facilityList = facilityRepository.facilityListing(12, pageable);
if (sortByUserCount) {
Comparator<FacilityProjection> comparator = Comparator.comparing(FacilityProjection::getUserCount);
if(desc) {
comparator = comparator.reversed();
}
Collections.sort(facilityList.getContent(), comparator);
}
As far as I know, this is not possible.
Having said that, I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(Facility.class)
public interface FacilityProjection {
#IdMapping
Long getId();
String getName();
#Mapping("SIZE(users)")
Long getUsercount();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
FacilityProjection a = entityViewManager.find(entityManager, FacilityProjection.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features so you can see this as a replacement for Spring Data Projections that supports more use cases!

How to write a query using spring jpa to fetch all rows from a database that are matching the string we pass?

Hi I am new to spring boot. I have a table having the following attributes: id,firstName,secondName,lastName.
Now I need to write a query (in repository), to find all those rows in my table whose firstName or secondName or lastName matches with the string I am passing.
eg: if I am passing 'foo' then it should search all the three columns and return those rows having 'foo' in any of them(this is pattern matching).
How can I do that? Thanks in advance.
You can use Like query on multiple column like this way
public interface UserRepository extends PagingAndSortingRepository<User,Long> {
#Query(value="select u from User u where u.firstName = %searchtext% or u.lastName= %searchtext% or u.secondName= %searchtext%")
Page<User> findByAllColumns(#Param("searchtext") String searchtext, Pageable pageable);
}
you can try with the below code
public List<Employee> findByFirstNameIgnoreCaseContainingOrSecondNameIgnoreCaseContainingOrLastNameIgnoreCaseContaining(String firstName,String secondName,String lastName);

Spring Data JPA findAllBy ... in ... orderBy input list

I'm using JPA with Spring Boot in Kotlin/Java. I'm trying to find the proper and efficient way to do findBy ... In OrderBy input.
I got a list of the Ids I want to find and I want an ordered output with the same order. This is what JPA allows you:
#Repository
interface PhotoRepository : JpaRepository<Photo, String>{
// Which is the same as this query
#Query("SELECT p FROM Photo p where p.id in :var1")
fun findAllByIdIn(var1: List<String>, pageable: Pageable): List<Photo>
}
Would be great if JPA allows you to do something like this:
#Repository
interface PhotoRepository : JpaRepository<Photo, String>{
#Query("SELECT p FROM Photo p where p.id in :var1 order by :var1")
fun findAllByIdInOrderByvar1(var1: List<String>, pageable: Pageable): List<Photo>
}
The size of the id list is between 500- 1500 items. There are lots of records in the database and the idea of select all the records is not feasible
The contemplated solution is to do a findAllByIdIn and then match the records with the ids in list, which I think is not the proper solution, there are extra operations. The idea of changing the database is also contemplated.
Once you get all the items in a certain id, with findAllByIdIn, to get the correct order, I used the following method:
private fun getOrderedItemsFromOneListToAnother(photosOrder: List<String>,
photosFound: List<Photo>): List<Photo>{
val mapStringIdsOrder = photosOrder.mapIndexed { index, s -> s to index}.toMap()
Collections.sort(photosFound, Comparator { o1: Photo, o2: Photo->
Integer.compare(mapStringIdsOrder.getOrDefault(o1.id,photosOrder.size),
mapStringIdsOrder.getOrDefault(o2.id, photosOrder.size))})
return photosOrder
}

Categories