mongodb java MongoTemplate与项目嵌套文档聚合

6jjcrrmo  于 2022-11-22  发布在  Go
关注(0)|答案(3)|浏览(159)

我有一份文件。

{
"errors" : [
    {
        "priority" : 3,
        "category" : "aaa"
        "other":"nothing"
    },
    {
        "priority" : 4,
        "category" : "bbb"
        "other":"nothing"
    },
    {
        "priority" : 2,
        "category" : "ccc"
        "other":"nothing"
    },
    {
        "priority" : 3,
        "category" : "ddd"
        "other":"nothing"
    },
    {
        "priority" : 2,
        "category" : "eee"
        "other":"nothing"
    }
    ],
"file_name" : "xxx.json",
"vehicle_id" : "esdf",
"day" : "2022-03-08"
}

我用js客户端执行一个命令。

db.wty_test.aggregate({
    $project: {
        '_id': 0, 'errors.priority': 1, 'errors.category': 1, 'file_name': 1, 'vehicle_id': 1,
    }
})

x1c 0d1x错误是一个包含对象的数组。
现在我需要用java客户端(springboot-data-mongo)覆盖这个命令。这是我的java代码。

import org.springframework.data.mongodb.core.MongoTemplate;
...
Aggregation aggregation = Aggregation.newAggregation(Aggregation.project("errors.priority", "errors.category", "file_name", "vehicle_id"));
mongoTemplate.aggregate(aggregation, "wty_test", HashMap.class).getMappedResults();


优先级和类别没有错误。

如何使用java获得与js相同的结果?

我试过了,但不是我想要的。

0s0u357o

0s0u357o1#

下面是一种获得所需结果的方法。

Document projectn = new Document("$project", 
                        new Document("_id", 0L)
                        .append("file_name", 1L)
                        .append("vehicle_id", 1L)
                        .append("errors", 
                            new Document("$map", 
                                new Document("input", "$errors")
                                .append("in", 
                                    new Document("priority", "$$this.priority")
                                    .append("category", "$$this.category")
                                )
                            )
                        )
                    );

List<Document> pipeline = Arrays.asList(projectn);
List<Document> results = mongoOps.getCollection("collection_name")
                                 .aggregate(pipeline)
                                 .into(new ArrayList<>());

注意,这里使用了MongoDB Java Driver API查询语法,Documentorg.bson.Document。本地查询到Java Driver的转换使用了$map聚合数组运算符(看起来这是(可能是唯一的)方法)。
对于MongoTemplate.aggregate,代码为:

Aggregation agg = newAggregation(
            project() 
            .and( 
                VariableOperators.Map.itemsOf("errors")
                    .as("e")
                    .andApply(ctx -> new Document("priority", "$$e.priority").append("category", "$$e.category") ))
            .as("errors")
            .andExclude("_id")
            .andInclude("file_name", "vehicle_id")
    );

    AggregationResults<Document> results = mongoOps.aggregate(agg, "collection_name", Document.class);

替代方法:

如果你的查询只是关于 projection 的,你可以使用MongoTemplate#find方法来查询,这样构造和理解起来要简单得多:

db.collection.find(
    {}, // your query filter
    { _id: 0, 'errors.category': 1, 'errors.priority': 1, file_name: 1, vehicle_id: 1 }
)

它的MongoTemplate版本:

Query query = new Query();
query.fields()
     .include("errors.priority", "errors.category", "file_name", "vehicle_id")
     .exclude("_id");
List<Document> results = mongoOps.find(query, Document.class, "collection_name");
nwsw7zdq

nwsw7zdq2#

您需要使用nested()函数,如下所示:

AggregationOperation project = Aggregation.project("file_name", "vehicle_id").
    and("errors").nested(Fields.fields("priority","category"))

Aggregation aggregation = Aggregation.newAggregation(project);
cwtwac6a

cwtwac6a3#

List<String> projectFieldSet = Arrays.asList("errors.category","errors.priority");
List<Field> fieldList = projectFields.stream().map(f->{return Fields.field(f,f);}).collect(Collectors.toList());        
ProjectionOperation projectAggOp = Aggregation.project(Fields.from(fieldList.toArray(new Field[fieldList.size()])));

相关问题