You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data MongoDB:用Criteria实现含$expr的Mongo查询等价逻辑

Solution for Overlap Rate Filtering in Spring Data MongoDB 2.0.x

Since Spring Data MongoDB 2.0.5 doesn't support the $expr operator directly in the Criteria API, we have two solid workarounds to replicate your existing MongoDB Shell logic. Let's break them down:

Option 1: Use BasicQuery for Native MongoDB Syntax

This approach lets you reuse your already-tested Shell query directly in Spring Data, avoiding the limitations of the Criteria API for this specific case.

Here's how to implement it:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Query;
import java.util.List;

// Inject your MongoTemplate instance
private final MongoTemplate mongoTemplate;

// Define your parameters
double overlapThreshold = 0.5;
int startInterval = 10;
int endInterval = 90;

public List<Variant> findDocumentsWithOverlap() {
    // Build the native query string (matches your Shell logic)
    String nativeQuery = String.format(
        "{ $expr: { $gt: [ { $divide: [ { $subtract: [ { $min: [ \"$end\", %d ] }, { $max: [ \"$start\", %d ] } ] }, %d ] }, %f ] } }",
        endInterval, startInterval, (endInterval - startInterval), overlapThreshold
    );

    // Create a BasicQuery with the native syntax
    Query query = new BasicQuery(nativeQuery);

    // Execute the query and map results to your entity class
    return mongoTemplate.find(query, Variant.class, "variants");
}

Pros: Directly reuses your validated Shell logic, minimal code changes.
Cons: Requires string formatting, which can be error-prone if you have many dynamic parameters (but manageable for this use case).

Option 2: Use Spring Data Aggregation Framework

This is a more type-safe, Spring Data-native approach using the Aggregation API, which supports all the arithmetic and comparison operators you need.

Here's the implementation:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.ArithmeticOperators;
import org.springframework.data.mongodb.core.aggregation.ComparisonOperators;
import org.springframework.data.mongodb.core.aggregation.Expressions;
import java.util.List;

// Inject your MongoTemplate instance
private final MongoTemplate mongoTemplate;

// Define your parameters
double overlapThreshold = 0.5;
int startInterval = 10;
int endInterval = 90;

public List<Variant> findDocumentsWithOverlapViaAggregation() {
    int intervalRange = endInterval - startInterval;

    // Build the match operation to filter by overlap rate
    var matchOperation = Aggregation.match(
        ComparisonOperators.Gt.valueOf(
            ArithmeticOperators.Divide.valueOf(
                ArithmeticOperators.Subtract.valueOf(
                    Expressions.min(Expressions.field("end"), endInterval)
                ).subtract(
                    Expressions.max(Expressions.field("start"), startInterval)
                )
            ).divideBy(intervalRange)
        ).greaterThanValue(overlapThreshold)
    );

    // Create the aggregation pipeline and execute
    var aggregation = Aggregation.newAggregation(matchOperation);
    return mongoTemplate.aggregate(aggregation, "variants", Variant.class).getMappedResults();
}

Pros: Type-safe, no string manipulation, aligns with Spring Data best practices.
Cons: Slightly more verbose than the native query approach, but easier to maintain for dynamic parameters.

Both approaches will correctly filter documents where the overlap rate with your target interval exceeds 50%, just like your original Shell query.

内容的提问来源于stack exchange,提问作者jizuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:38:16