8

I am iterating over a list of key/value pairs and executing find for each key/value. Can I create a single query document to be kind of union in sql, So that there will be only one database call.

    List<User> userList = new ArrayList<User>();
    for (Map accounts:attributes) {
        Query query = new Query();
        List<Criteria> andCriteriaList = new ArrayList<Criteria>();
        accounts.forEach((key, value) -> {
            Criteria criteria = Criteria.where((String) key).is(value);
            andCriteriaList.add(criteria);
        });
        query.addCriteria(new Criteria().andOperator(andCriteriaList.toArray(new Criteria[andCriteriaList.size()])));
        if (mongoTemplate.exists(query, User.class)) {
            userList.add((User)mongoTemplate.find(query, User.class));
            //System.out.println(mongoTemplate.find(query, User.class));
        }

Thanks,

4
  • You can use the $in operator. Something like Query query = new Query(); query.addCriteria(Criteria.where("UserID").in(userList.stream().map(User::getId).collect(Collectors.toList()))); List<User> users = mongoTemplate.find(query,User.class); Commented Aug 16, 2017 at 17:51
  • @Veeram, sorry I forgot to mention that the query document will be dynamic in nature and where condition can be different. I provided a more suitable example Commented Aug 16, 2017 at 18:00
  • Np.You can always prepare the Query object dynamically too from your incoming attributes. I saw the latest update. What problems are you running into while doing that conversion ? Commented Aug 16, 2017 at 18:09
  • @Veeram its working, but the query will be called each time for every attribute element. Cant we make it a single query and then send it to the database. Commented Aug 16, 2017 at 18:35

2 Answers 2

17

You can refactor your code to create $or expressions. No explicit $and operator needed.

Something like

 Query orQuery = new Query();
 Criteria orCriteria = new Criteria();
 List<Criteria> orExpression =  new ArrayList<>();
 for (Map<String, Object> accounts : attributes) {
   Criteria expression = new Criteria();
   accounts.forEach((key, value) -> expression.and(key).is(value));
   orExpression.add(expression);
 }
 orQuery.addCriteria(orCriteria.orOperator(orExpression.toArray(new Criteria[orExpression.size()])));
 List<User> userList = mongoOperations.find(orQuery, User.class);

This should output query like

{ "$or" : [{ "key1" : "value1", "key2" : "value2" }, { "key3" : "value3", "key4" : "value4" }] }
Sign up to request clarification or add additional context in comments.

Comments

13

if you want to query multiple fields(field1, field2, ....) with values below is the solution

Query query = new Query();
List<Criteria> criteria = new ArrayList<>();

criteria.add(Criteria.where(field1).is(field1val));
criteria.add(Criteria.where(field2).is(field2val));
// you can add all your fields here as above

query.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[criteria.size()])));
List<JSONObject> filteredVals = mongoOperations.find(query, JSONObject.class);

the above return filteredVals is JSONObject

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.