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

时间:2015-03-26 13:34:41

标签: java mongodb spring-data spring-data-mongodb

mongodb中无法在简单SQL中看起来很自然。

给出一个简单的文件:

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

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

据我所知,它应该像其他条件一样微不足道。

在Spring api上找不到任何支持它。

4 个答案:

答案 0 :(得分:4)

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

Native 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时需要注意一些 considerations

  

不要使用全局变量。

     

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

     

MongoDB将在$ where之前评估非$ where查询组件   声明。如果非$ where语句不匹配任何文档,MongoDB   不会使用$ 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);

答案 1 :(得分:4)

您可以使用以下模式:

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);

答案 2 :(得分:1)

感谢@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);

答案 3 :(得分:0)

这是一种方法:

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);

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