【问题标题】:User projected field as criteria for a MatchOperation in Spring Boot 2 and MongoDB用户投影字段作为 Spring Boot 2 和 MongoDB 中 MatchOperation 的标准
【发布时间】:2019-04-16 14:57:24
【问题描述】:

我花了几个小时寻找一种方法来做到这一点,但我没有发现任何有用的方法。

我会尽量简短。我有一个包含几个步骤的聚合。在第一步中我分组,然后我用表达式投影几个字段(进行一些计算),最后我想使用这些投影字段(我的计算结果)作为下一个匹配阶段的条件:

    Cond condOperation = ConditionalOperators.when(Criteria.where("productRulesValues.maxTerm").lte("$availableYears"))
            .thenValueOf("$productRulesValues.maxTerm")
            .otherwise("$availableYears");

    TypedAggregation<ProductRulesValues> aggregationProducts = Aggregation.newAggregation(ProductRulesValues.class,
            Aggregation.group("productType")
                    .last("$$ROOT").as("productRulesValues"),
            project("productRulesValues")
                    .andExpression("productRulesValues.maxAge - [0]", formHipooWizard.getAge()).as("availableYears"),
            project("productRulesValues")
                    .and(condOperation).as("duration"),
            new MatchOperation(Criteria.where("productRulesValues.maxTerm").is("$duration"))
    );

与我正在寻找的最接近的答案是https://stackoverflow.com/a/29280577/7206287,但它使用 DBObject 的旧方法。

我已经尝试过使用 org.bson.Document 更改 DBObject 的这种方式,因为它是现在使用的但没有运气(它抱怨 $where 子句)。参考:

https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/query/CriteriaDefinition.html

我不太明白的一点是,当我定义第一个条件时,使用文档属性和投影属性没有问题。

如果不是:

new MatchOperation(Criteria.where("productRulesValues.maxTerm").is("$duration")

我用文字过滤持续时间,它就像一个魅力,所以持续时间具有正确的内存值:

new MatchOperation(Criteria.where("duration").is(30)

有什么解决方法吗?

谢谢!

【问题讨论】:

    标签: mongodb spring-boot spring-data aggregation-framework spring-data-mongodb


    【解决方案1】:

    这是预期的行为。

    第一个条件中的聚合表达式允许您比较文档字段。因此,在 3.6 之前,所有匹配查询都会与静态值和文档字段进行比较。

    从 3.6 开始,您必须使用特殊的运算符 $expr,它允许在匹配查询中使用聚合表达式。

    春季还不支持$expr。

    你必须使用投影来添加新的字段来保存比较,然后是匹配操作和额外的投影来删除比较字段。

    Cond condOperation = ConditionalOperators.when(Criteria.where("productRulesValues.maxTerm").lte("$availableYears"))
            .thenValueOf("$productRulesValues.maxTerm")
            .otherwise("$availableYears");
    
    TypedAggregation<ProductRulesValues> aggregationProducts = Aggregation.newAggregation(ProductRulesValues.class,
            Aggregation.group("productType")
                    .last("$$ROOT").as("productRulesValues"),
            project("productRulesValues")
                    .andExpression("productRulesValues.maxAge - [0]", formHipooWizard.getAge()).as("availableYears"),
            project("productRulesValues")
                    .and(condOperation).as("duration").and(ComparisonOperators.Eq.valueOf("productRulesValues.maxTerm").equalOf("duration")).as("comp"),
            new MatchOperation(Criteria.where("comp").is(true)),
            project().andExclude("comp");
    );
    

    从 3.4 开始支持带有排除项的 Note 项目。

    【讨论】:

    • 这样就可以了,谢谢!我正在考虑类似的事情,但我想我已经饱和了,没有看到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多