繁体   English   中英

如何使用查询对象比较 Spring Data MongoDB 中的 2 个字段

[英]How to compare 2 fields in Spring Data MongoDB using query object

在简单的 SQL 中看似自然的事情在mongodb是不可能的。

给定一个简单的文档:

{
    "total_units" : 100,
    "purchased_unit" : 60
}

我想使用 spring 数据 Criteria 类查询集合,其中"total_units > purchased_units"

据我了解,它应该与任何其他条件一样微不足道。

在 Spring api 上找不到任何支持此功能的内容。

您可以使用以下模式:

Criteria criteria = new Criteria() {
    @Override
    public DBObject getCriteriaObject() {
        DBObject obj = new BasicDBObject();
        obj.put("$where", "this.total_units > this.purchased_units");
        return obj;
    }
};

Query query = Query.query(criteria);

我认为 Spring Data API 尚不支持此功能,但您可能需要将$where查询包装在 Java 本机 DbObject 中。 请注意,您的查询性能将受到相当大的影响,因为它会评估每条记录上的 Javascript 代码,因此如果可以,请结合索引查询。

原生 Mongodb 查询:

db.collection.find({ "$where": "this.total_units > this.purchased_units" });

本机 Java 查询:

DBObject obj = new BasicDBObject();
obj.put( "$where", "this.total_units > this.purchased_units");

使用$where时必须考虑的一些注意事项

不要使用全局变量。

$where 评估 JavaScript,不能利用索引。 因此,当您使用标准 MongoDB 运算符(例如,$gt、$in)表达查询时,查询性能会提高。 通常,只有在无法使用其他运算符表达查询时才应使用 $where。 如果必须使用 $where,请尝试至少包含一个其他标准查询运算符来过滤结果集。 单独使用 $where 需要进行表扫描。 使用普通的非 $where 查询语句提供以下性能优势:

MongoDB 将在 $where 语句之前评估查询的非 $where 组件。 如果非 $where 语句不匹配任何文档,MongoDB 将不会使用 $where 执行任何查询评估。 非 $where 查询语句可能使用索引。

据我所知你不能做query.addCriteria(Criteria.where("total_units").gt("purchased_units"));

但是会按照您的建议创建一个额外的计算字段,比如computed_units ,它是total_unitspurchased_units之间的差异,然后您可以查询为:

Query query = new Query();
query.addCriteria(Criteria.where("computed_units").gt(0));

mongoOperation.find(query, CustomClass.class);

感谢@Andrew Onischenko 提供历史性的好答案。

在最新版本的 spring-data-mongodb(例如 2.1.9.RELEASE)上,我必须编写如下相同的模式:

import org.bson.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

// (...)

Criteria criteria = new Criteria() {
    @Override
    public Document getCriteriaObject() {
        Document doc = new Document();
        doc.put("$where", "this.total_units > this.purchased_units");
        return doc;
    }
};

Query query = Query.query(criteria);

一种方法是这样的:

Criteria c = Criteria.where("total_units").gt("$purchased_unit");
AggregationOperation matchOperation = Aggregation.match(c);
Aggregation aggregation = Aggregation.newAggregation(matchOperation);
mongoTemplate.aggregate(aggregation, "collectionNameInStringOnly", ReturnTypeEntity.class);

请记住将集合名称放在字符串中,以便将标准中提到的字段的拼写与数据库集合中的字段相匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM