首页 > 解决方案 > MongoDB Aggregation - 如何使用 spring-data-mongodb 将查询表达式应用到匹配阶段?

问题描述

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

示例实体

@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

标签: javamongodbaggregation-frameworkspring-data-mongodb

解决方案


您可以实现自己的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"))
    ));
}

推荐阅读