【问题标题】:MongoDB Aggregation - How can i apply query expression into match stage using spring-data-mongodb?MongoDB Aggregation - 如何使用 spring-data-mongodb 将查询表达式应用到匹配阶段?
【发布时间】:2021-12-06 23:59:05
【问题描述】:

我有包含动态字段的文档,我需要为给定的复杂查询条件找到匹配记录的计数

示例实体

@Document(collection = "UserAttributes")
public class UserAttributesEntity {

    @Id
    @Getter
    private String id;

    @NotNull
    @Size(min = 1)
    @Getter @Setter
    private String userId;

    @NotNull
    @Getter @Setter
    private Map<String, Object> attributes = new HashMap<>();
}

示例数据

{
    "_id" : ObjectId("6164542362affb14f3f2fef6"),
    "userId" : "89ee6942-289a-48c9-b0bb-210ea7c06a88",
    "attributes" : {
        "age" : 61,
        "name" : "Name1"
    }
},
{
    "_id" : ObjectId("6164548045cc4456792d5325"),
    "userId" : "538abb29-c09d-422e-97c1-df702dfb5930",
    "attributes" : {
        "age" : 40,
        "name" : "Name2",
        "location" : "IN"
    }
}

预期的查询表达式

"((attributes.name == 'Name1' && attributes.age > 40) OR (attributes.location  == 'IN'))

$match 的 MongoDB 聚合查询如下所示,但通过 spring mongo db api 不可用:

{ 
    $expr: 
    { 
        "$and": [{
            "$gt": ["$attributes.age", 40]
        }, {
            "$eq": ["$attributes.name", "Name2"]
        }] 
    }
}

我这里有什么遗漏吗?

库使用:org.springframework.data:spring-data-mongodb:3.1.1

【问题讨论】:

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


    【解决方案1】:

    您可以实现自己的AggregationOperation 来处理您不同的情况。 我自己的代码没试过,不过应该是这样的:

    AggregationOperation myMatch (List<Document> conditions) {
    
        return new AggregationOperation() {
    
            @Override
            public String getOperator() {
                return "$match";
            }
    
            @Override
            public Document toDocument(AggregationOperationContext context) {
                return new Document("$match",
                        new Document("$expr",
                                new Document("$and", conditions)
                        )
                );
            }
        };
    }
    

    并以这种方式调用它(以匹配您的问题查询):

    void callMyMatch() {
        myMatch(List.of(
            new Document("$gt", List.of("$attributes.age", 40)),
            new Document("$eq", List.of("$attributes.name", "Name2"))
        ));
    }
    

    【讨论】:

    • 谢谢@orid。是的,我可以执行上述方法,甚至我也可以尝试根据查询动态创建 Criteria 对象,但我会期待一些具有嵌套条件的复杂查询,因此希望我是否可以简单地使用 SPEL 来评估查询表达式?类似问题:stackoverflow.com/questions/69635474/… 寻找一种直接传入表达式而不像上面那样构建它的方法:"((attributes.name == 'Name1' &amp;&amp; attributes.age &gt; 40) OR (attributes.location == 'IN'))"
    猜你喜欢
    • 2015-12-17
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多