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.
Related
I am doing a room database
#Query("SELECT distinct UserID FROM USER WHERE CovidStat=='T'")
public List<USER> checkCovid();
#Query("SELECT DISTINCT PID,VisitDate FROM USER_PLACE,USER WHERE User.UserID=USER_PLACE.UID AND UID=(:UID)")
int selectCovidPlace(int UID);
I wanted checkCovid() to return UserID where CovidStat='T' and I wanted to put the ID into selectCovidPlace to identify which place that ID been to. The problem is that checkCovid would return me a list instead of 1 variable since its not only 1 person who would have CovidStat='T', but im not sure that how can I put a list into selectCovidPlace().
I'm not familiar with SQLite. But the SQL syntax should be generic.
How about use IN statement?
like this ... WHERE User.UserID=USER_PLACE.UID AND UID IN (:UID)")
And then you can pass List as parameter.
Here you should use IN clause as below:
#Query("SELECT DISTINCT PID,VisitDate FROM USER_PLACE,USER WHERE User.UserID=USER_PLACE.UID AND UID IN (:UIDs)")
int selectCovidPlace(List<Integer> UIDs);
Consider this code snippet below:
List<String> usersList = Arrays.asList("john", "jack", "jill", "xxxx", "yyyy");
List<User> userEntities = userRepo.findAllById(usersList);
User class is a simple Entity object annotated with #Entity and has an #Id field which is of String datatype.
Assume that in db I have rows corresponding to "john", "jack" and "jill". Even though I passed 5 items in usersList(along with "xxxx" and "yyyy"), findAllById method would only return 3 items/entities corresponding to "john","jack",and "jill".
Now after the call to findAllById method, what's the best, easy and efficient(better than O(n^2) perhaps) way to find out the missing items which findAllById method did not return?(In this case, it would be "xxxx" and "yyyy").
Using Java Sets
You could use a set as the source of filtering:
Set<String> usersSet = new HashSet<>(Arrays.asList("john", "jack", "jill", "xxxx", "yyyy"));
And now you could create a predicate to filter those not present:
Set<String> foundIds = userRepo.findAllById(usersSet)
.stream()
.map(User::getId)
.collect(Collectors.toSet());
I assume the filter should be O(n) to go over the entire results.
Or you could change your repository to return a set of users ideally using a form of distinct clause:
Set<String> foundIds = userRepo.findDistinctById(usersSet)
.stream()
.map(User::getId)
.collect(Collectors.toSet());;
And then you can just apply a set operator:
usersSet.removeAll(foundIds);
And now usersSet contains the users not found in your result.
And a set has a O(1) complexity to find an item. So, I assume this should be O(sizeOf(userSet)) to remove them all.
Alternatively, you could iterate over the foundIds and gradually remove items from the userSet. Then you could short-circuit the loop algorithm in the event you realize that there are no more userSet items to remove (i.e. the set is empty).
Filtering Directly from Database
Now to avoid all this, you can probably define a native query and run it in your JPA repository to retrieve only users from your list which didn't exist in the database. The query would be somewhat as follows that I did in PostgreSQL:
WITH my_users AS(
SELECT 'john' AS id UNION SELECT 'jack' UNION SELECT 'jill'
)
SELECT id FROM my_users mu
WHERE NOT EXISTS(SELECT 1 FROM users u WHERE u.id = mu.id);
Spring Data: JDBC Example
Since the query is dynamic (i.e. the filtering set could be of different sizes every time), we need to build the query dynamically. And I don't believe JPA has a way to do this, but a native query might do the trick.
You could either pack a JdbcTemplate query directly into your repository or use JPA native queries manually.
#Repository
public class UserRepository {
private final JdbcTemplate jdbcTemplate;
public UserRepository(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}
public Set<String> getUserIdNotFound(Set<String> userIds) {
StringBuilder sql = new StringBuilder();
for(String userId : userIds) {
if(sql.length() > 0) {
sql.append(" UNION ");
}
sql.append("SELECT ? AS id");
}
String query = String.format("WITH my_users AS (%sql)", sql) +
"SELECT id FROM my_users mu WHERE NOT EXISTS(SELECT 1 FROM users u WHERE u.id = mu.id)";
List<String> myUsers = jdbcTemplate.queryForList(query, userIds.toArray(), String.class);
return new HashSet<>(myUsers);
}
}
Then we just do:
Set<String> usersIds = Set.of("john", "jack", "jill", "xxxx", "yyyy");
Set<String> notFoundIds = userRepo.getUserIdNotFound(usersIds);
There is probably a way to do it with JPA native queries. Let me see if I can do one of those and put it in the answer later on.
You can write your own algorithm that finds missing users. For example:
List<String> missing = new ArrayList<>(usersList);
for (User user : userEntities){
String userId = user.getId();
missing.remove(userId);
}
In the result you will have a list of user-ids that are missing:
"xxxx" and "yyyy"
You can just add a method to your repo:
findByIdNotIn(Collection<String> ids) and Spring will make the query:
See here:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
Note (from the docs):
In and NotIn also take any subclass of Collection as aparameter as well as arrays or varargs.
I am working on spring boot and Hibernate and
I need data from different table in mysql database so I ran custom query that to get data from different tables.And my query is,
#Query(value = "Select i.item_id,i.item_name,s.size_name,sp.Prices from mt_item i join mt_sizeprice sp on i.item_id= sp.item_id join mt_size s on sp.size_id=s.size_id where i.merchant_fk= ?1 and is_featured=1",nativeQuery = true)
List<Object> get(long merchantId);
The result of the query is,
As the data is from different table I am unable to map List of data of Object into the List of my model class as,
List<Object> get(long merchantId); to
List<FavoriteItem> list = new ArrayList<>();
It seems the result of your query will be List of Object[] instead of Object List. You can pass result to method and create List of FavoriteItem by iterating over results.
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!
I got a Set<UserDTO> collection in a not Hibernate object, and I got a User domain entity in Hibernate.
UserDTO contains less information about user (only id and name)
How can I select full Hibernate User Set/List from the DTO object?
Like this?
Set<UserDTO> setDTO = .....
String hql = "FROM User WHERE id IN (:userDTO )";
Query query = entityManager.createQuery(hql);
query.setParameter("userDTO", setDTO);
return query.getResultList();
Thanks
Almost. But you'd have to extract the IDs in a separate collection first:
Set<Long> ids = new HashSet<Long>(setDTO.size());
for (UserDTO dto : setDTO) {
ids.add(dto.getId());
}
Then proceed with the query, and pass the ids set as param.
Don't forget that you need to use Query#setParameterList() instead of Query#setParameter.