我有这样的方法:
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;
这段代码看起来效率低下,因为它访问 db 的字段数组大小如此之多。
有没有办法使用单个查询来替换它?
最佳答案
为什么不使用 Criteria::in方法并传递一个列表而不是迭代所有元素并逐个元素检查,我认为你只需要这个:
query.addCriteria(
Criteria.where("data." + fieldName).in(fieldArray)
);
除了@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
对于流,您可以使用:
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;
尽管从技术上讲是正确的,但当您运行代码时您将得到 p>
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"}]'. Criteria already contains '$or : [ { "data.field1" : "some_constant"}]'.
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()])));
输出:
{ "$or" : [ { "data.field1" : "some_constant"} , { "data.field2" : "some_constant"} , { "data.field3" : "some_constant"}]}
关于java - 如何检查该值至少等于列表中的一个字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47906232/