如何在Spring中编写这个Mongo聚合查询?

soa*_*gem 2 java spring mongodb spring-data spring-data-mongodb

我在MongoDB中有一个聚合查询,直接在shell中运行它.这是shell查询:

db.MyCollection.aggregate([
    {$match: {_id: {$in: ['A', 'B', 'C']}}},
    {$project: {"versions": "$nested.field.version"}},
    {$unwind: "$versions"},
    {$group: {_id: "$_id", "maxVersion": {$max: "$versions"}}}
])
Run Code Online (Sandbox Code Playgroud)

如您所见,这可以做到以下几点:

  1. 仅匹配具有指定ID的某些文档
  2. 将嵌套字段投影到基础级字段(并有效过滤掉管道中的所有其他字段,但仍保留ID)
  3. 展开我们投影到管道中各个文档的$ versions字段的数组元素
  4. 查找每个ID的这些$版本的最大值

就像我说的,上面的查询已经有效了.我的问题是如何将其转换为Spring MongoDB语法.这是我第一次尝试,这并没有工作:

Aggregation aggregation = newAggregation(
    match(Criteria.where("_id").in(listOfIds))
    ,project().and("versions").nested(bind("versions", "nested.field.version"))
    ,unwind("versions")
    ,group("_id").max("versions").as("maxVersion")
);
Run Code Online (Sandbox Code Playgroud)

当我尝试在调试模式下运行代码时,我可以看到我实际上在newAggregation上得到一个IllegalArgumentException,说它无法评估.如果我用$ group子句注释掉这一行,那么我可以看到聚合变量的这个toString()表示,它揭示了$ project子句的问题:

{
  "aggregate" : "__collection__" ,
  "pipeline" : [
    { "$match" : { "_id" : { "$in" : [ "A" , "B" , "C"]}}} ,
    { "$project" : { "versions" : { "versions" : "$nested.field.version"}}} ,
    { "$unwind" : "$versions"}
  ]
}
Run Code Online (Sandbox Code Playgroud)

显然,这与我的意图不符,所以我没有得到正确的语法.但TBH我没有发现Spring MongoOps语法非常直观,他们的文档也不是很好.

如果没有先调用,我就没有办法调用该nested()方法and().我认为这是主要的问题,因为它在那里加倍筑巢.有没有Spring MongoOps英雄可以帮助我正确编写等效的Java代码?

编辑:这是我正在使用的集合的快照:robomongo显示

chr*_*dam 6

$project,因为你仍然可以做一个管道是没有必要$unwind的嵌套的领域,因此该管道的聚集能得到相同的结果,当前的:

db.MyCollection.aggregate([
    {
        "$match": {
            "_id": { "$in": ['A', 'B', 'C'] }
        }
    },
    { "$unwind": "$nested.field" },
    {
        "$group": {
            "_id": "$_id", 
            "maxVersion": { "$max": "$nested.field.version" }
        }
    }
])
Run Code Online (Sandbox Code Playgroud)

Spring Data MongoDB聚合等效:

Aggregation agg = newAggregation(
        match(Criteria.where("_id").in(ids)),
        unwind("nested.field"),        
        group("_id").max("nested.field.version").as("maxVersion")
    );
Run Code Online (Sandbox Code Playgroud)

回到你当前的聚合,你需要$unwindnested.field数组,而不是nested.field.version字段,因为那是一个字符串,而不是数组:

db.MyCollection.aggregate([
    {$match: {_id: {$in: ['A', 'B', 'C']}}},
    {$project: {"fields": "$nested.field"}},
    {$unwind: "$fields"},
    {$group: {_id: "$_id", "maxVersion": {$max: "$fields.version"}}}
])
Run Code Online (Sandbox Code Playgroud)

Sprind Data MongoDB等价物看起来像:

Aggregation agg = newAggregation(
        match(Criteria.where("_id").in(ids)),
        project().and("nested.field").as("fields")
        unwind("fields"),        
        group("_id").max("fields.version").as("maxVersion")
    );
Run Code Online (Sandbox Code Playgroud)

  • 那么,你的回答是正确的.不幸的是,由于Spring Data的一个错误,它在我的特定情况下无法工作.我总是在发布SO之前清理我的字段名称,但实际上我在一些嵌套字段名称中有下划线,看起来Spring Data在进行一些导致它失败的参照完整性检查时会对下划线进行某种拆分.所以感谢您的努力,但遗憾的是,Spring Data在我的用例中使用起来太麻烦了. (2认同)