【问题标题】:How to compare 2 fields in Spring Data MongoDB using query object如何使用查询对象比较 Spring Data MongoDB 中的 2 个字段
【发布时间】:2015-03-26 13:34:41
【问题描述】:

在简单 SQL 中看起来几乎很自然的事情在 mongodb 中是不可能的。

给定一个简单的文档:

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

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

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

在 Spring api 上找不到任何支持这一点的东西。

【问题讨论】:

  • 我认为 Spring Data API 不支持这一点,但您可能需要将 $where 查询包装在您的 Java 本机 DbObject
  • @chridam,你能添加一个简单的例子吗?

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


【解决方案1】:

您可以使用以下模式:

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

【讨论】:

  • 在我的例子中,两个字段的比较就像字符串比较一样。这个技巧奏效了:this.total_units - this.purchased_units > 0getCriteriaObject 也可以更短:return new BasicDBObject("$where", "this.total_units > this.purchased_units");
【解决方案2】:

我认为 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");

一些considerations你在使用$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);

【讨论】:

  • 感谢您的回答。但是,这些示例不是 spring-data 方式。我花了将近 2 天的时间寻找解决方案,但没有运气。我想我需要在此文档中添加新字段来表示“total_units - purchase_units”的值
  • 我也会选择这条路线
  • @HananBareket 你能试试下面的:query.addCriteria(Criteria.where("this.total_units > this.purchased_units")?
  • 已经做到了。不工作。我想我错过了一些东西。不支持任何查询语言中如此基本的东西是没有任何意义的。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    一种方法是这样的:

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

    记得将集合名称放在字符串中,以便将条件中提到的字段的拼写与数据库集合中的字段匹配。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-08
      • 1970-01-01
      • 2019-07-02
      • 2012-02-08
      • 1970-01-01
      • 2016-07-10
      相关资源
      最近更新 更多