[英]How to check that value equals at least one field from list?
I have method like this: 我有这样的方法:
for (String fieldName : fieldArray) {
Query query = new Query();
query.addCriteria(Criteria.where("data." + fieldName).is("some_constant"));
if (mongoTemplate.find(query, DataPoint.class).size() > 0) {
return true;
}
}
return false;
This code looks inefficient because it access to db so much how fieldArray size. 这段代码看起来效率低下,因为它访问db这么多fieldArray的大小。
Is there way to replace it using single query? 有没有办法用单个查询替换它?
Why not using Criteria::in method and pass a List instead of Iterate over all the element and check element by element, I think you need just this : 为什么不在方法中使用Criteria ::并传递List而不是迭代所有元素并逐个元素检查,我认为你需要这样:
query.addCriteria(
Criteria.where("data." + fieldName).in(fieldArray)
);
Beside the comment of @Veeram the first way will work if you want to check if one field can hold one of the values in your list, but it seems that your problem is different, what i understand, you want to check a value exit in multiple fields, to solve this issue you can use : 除了@Veeram的注释之外,如果你想检查一个字段是否可以容纳列表中的一个值,第一种方式将起作用,但似乎你的问题不同,我理解,你想检查一个值退出多个字段,解决这个问题你可以使用:
//Consider you want to check in multiple fields
List<String> fieldArray = Arrays.asList("field1", "field2", "field3");
// First you have to create a list of Criteria (multiple conditions)
List<Criteria> listOfCondition = new ArrayList<>();
for (String fieldName : fieldArray) {
listOfCondition.add(
Criteria.where("data." + fieldName).is("some_constant")
);
}
//The add them to the query.
Criteria criteria = new Criteria();
for (Criteria c : listOfCondition) {
criteria = criteria.orOperator(c);
}
Query query = new Query();
query.addCriteria(criteria);
//Then execute your query just one time
With streams you can use : 使用流可以使用:
List<String> fieldArray = Arrays.asList("field1", "field2", "field3");
Criteria principaleCriteria = new Criteria();
fieldArray.stream()
.map(fieldName -> Criteria.where("data." + fieldName).is("some_constant"))
.forEach(criteria -> principaleCriteria.orOperator(criteria));
Query query = new Query();
query.addCriteria(principaleCriteria);
return mongoTemplate.count(query, DataPoint.class) > 0;
Although technically correct when you run the code you will get 虽然在运行代码时技术上是正确的,但您会得到
org.springframework.data.mongodb.InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDBObject, you can't add a second '$or' expression specified as '$or : [ { "data.field2" : "some_constant"}]'. org.springframework.data.mongodb.InvalidMongoDbApiUsageException:由于com.mongodb.BasicDBObject的限制,您无法添加第二个'$或'表达式,指定为'$或:[{“data.field2”:“some_constant” }]”。 Criteria already contains '$or : [ { "data.field1" : "some_constant"}]'. 标准已包含'$或:[{“data.field1”:“some_constant”}]'。
Mongodb compliant code: 符合Mongodb的代码:
List<String> fieldArray = Arrays.asList("field1", "field2", "field3");
Criteria principaleCriteria = new Criteria();
List<Criteria> orExpressions = fieldArray.stream()
.map(fieldName -> Criteria.where("data." + fieldName).is("some_constant"))
.collect(toList());
Query query = new Query();
query.addCriteria(principaleCriteria.orOperator(orExpressions.toArray(new Criteria[orExpressions.size()])));
Outputs: 输出:
{ "$or" : [ { "data.field1" : "some_constant"} , { "data.field2" : "some_constant"} , { "data.field3" : "some_constant"}]}
Seems to me that you could use public Criteria orOperator(Criteria... criteria)
在我看来,你可以使用public Criteria orOperator(Criteria... criteria)
It should be something like : 它应该是这样的:
List<Criteria> criterias = new ArrayList<>();
for (String fieldName : fieldArray) {
//Create the criterias like you want
criterias.add(Criteria.where("data." + fieldName).is("some_constant"));
}
Query query = new Query(
new Criteria().orOperator(
criterias.toArray( //convert the list into an Criteria[] for the varargs parameter
new Criteria[criterias.size()]
)
)
);
This will create a list of Criteria
that will be used to generate an Criteria instance that will be valid if one criteria is valid (OR operation, one true is enough). 这将创建一个Criteria
列表,用于生成Criteria实例,如果一个条件有效(OR操作,一个true就足够了),该实例将有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.