I am trying to query a mongodb collection with two 'or' clauses via Java API. The following query works fine when run through any mongo client:
{
$and : [{
$or : [ { “field1” : “value1”}, {“field1” : “value2”}]
},{
$or : [ { “field2” : “value3”} , { “field2” : “value4”}]
}]
}
But when I try to run this using Java API, I get the following error:
org.springframework.data.mongodb.InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDBObject, you can't add a second '$or' expression specified as '$or : [ { “field1” : “value1”}, {“field1” : “value2”}]'. Criteria already contains '$or : [ { “field2” : “value3”} , { “field2” : “value4”}]'.
at org.springframework.data.mongodb.core.query.Criteria.setValue(Criteria.java:640)
at org.springframework.data.mongodb.core.query.Criteria.getCriteriaObject(Criteria.java:573)
at org.springframework.data.mongodb.core.query.Criteria.createCriteriaList(Criteria.java:630)
at org.springframework.data.mongodb.core.query.Criteria.andOperator(Criteria.java:539)
You can do it through Java API by
1) preparing a list of your 'or' criterias.
2) create new criteria object.
3) 'feed' the list created in (1) into the object created in (2), using the criteria object's 'andOperator' method.
Something like this ->
Query query = new Query();
Map<String, String> params; // let's say this arrived with some values
List<Criteria> criterias = new ArrayList<>();
for (String k : params.keySet()) {
String paramVal = params.get(k);
switch (k) {
case "someVal1":
criterias.add(new Criteria().orOperator(Criteria.where("metadata.field1").is(paramVal),
Criteria.where("metadata.field2").is(paramVal)));
break;
case "someVal2":
criterias.add(new Criteria().orOperator(Criteria.where("metadata.arrayField3").in(paramVal),
Criteria.where("metadata.arrayField4").in(paramVal),
Criteria.where("metadata.arrayField5").in(paramVal)));
break;
default:
break;
}
}
if (criterias.size() > 0){
query.addCriteria(new Criteria().andOperator(criterias.toArray(new Criteria[criterias.size()])));
}
Try splitting that into an $in
operator. Let's break down the first $or
expression:
{
"$or": [
{ "filed1" : "value1" },
{ "filed1" : "value2" }
]
}
This can be converted into an $in
operator as
{ "field1": { "$in": ["value1", "value2"] } }
Similarly
{
"$or": [
{ "filed2" : "value3" },
{ "filed2" : "value4" }
]
}
can be expressed as
{ "field2": { "$in": ["value3", "value4"] } }
Combining the two expressions into one implicit AND query yields:
db.collection.find({
"field1": { "$in": ["value1", "value2"] },
"field2": { "$in": ["value3", "value4"] }
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With