java - 如何检查该值至少等于列表中的一个字段?

标签 java spring mongodb spring-data

我有这样的方法:

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;

尽管从技术上讲是正确的,但当您运行代码时您将得到

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/

相关文章:

java - 日历时区,它是如何工作的?

java - 了解 CSV 文件的分隔符

java - 我如何将参数添加到 Jersey 过滤器请求(ContainerRequestFilter)的请求

javascript - Mongoose 模型静态方法的TypeError

javascript - PHP/MongoDB 查询协助

python - mongoengine - 运行时错误 : generator raised StopIteration

java - 有人使用 SpringSource tc 服务器作为 Tomcat 替代品吗?

java - Spring batch JDBCPagingItemReader、ThreadPoolTask​​Executor 和 OpenShift 中的多个 pod

java - Spring 3.2.4 中测试 Controller 的替代方案

java - spring3 中有页面范围吗?