Mongodb Aggregation:投影没有最后一个元素的数组

时间:2017-11-22 11:38:26

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

在spring Data中使用聚合管道,我有包含嵌套数组的文档,我想要投影除最后一项之外的数组。 例如,对于每个文档,如:

{
    "_id" : ObjectId("59ce411c2708c97154d13150"),
    "doc1" : [ 
        {
            "nodeValue" : "AAA"
        }, 
        {
            "nodeValue" : "BBB"
        }, 
        {
            "nodeValue" : "CCC"
        }, 
        {
            "nodeValue" : "DDD"
        }
    ],
    "field2" : 20170102,
    "field3" : 4,
}

我想要结果:

{
    "_id" : ObjectId("59ce411c2708c97154d13150"),
    "doc1" : [ 
        {
            "nodeValue" : "AAA"
        }, 
        {
            "nodeValue" : "BBB"
        }, 
        {
            "nodeValue" : "CCC"
        }, 
        {
            "nodeValue" : "DDD"
        }
    ],
    "doc1_without_last" : [ 
        {
            "nodeValue" : "AAA"
        }, 
        {
            "nodeValue" : "BBB"
        }, 
        {
            "nodeValue" : "CCC"
        }
    ],
    "field2" : 20170102,
    "field3" : 4,
}

我试过这样的东西,但是我找不到一个可以弹出数组并从中移除最后一项的运算符。

Aggregation agg = Aggregation.newAggregation(
                      Aggregation.project()
                        .andInclude("doc1","field2","field3"),
                       Aggregation.project().and(ArrayOperators.arrayOf("doc1")..).as("doc1_without_last")

                       new OutOperation("newCollection")
                ).withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build());

感谢您的帮助

2 个答案:

答案 0 :(得分:2)

shell查询可以是这样的:

db.collection.aggregate([
    { $project: {
        doc1: 1,
        doc1_without_last: { $slice: [ 
            "$doc1", 
            { $subtract: [ { $size: "$doc1" }, 1 ] } 
        ] }
    } }
])

文档:

如果春天有任何限制,不允许您构建此类查询,则可以使用$let来使用查询变量:

db.collection.aggregate([
    { $project: {
        doc1: 1,
        doc1_without_last: { $let: {
            vars: { size: { $subtract: [ { $size: "$doc1" }, 1 ] } },
            in: { $slice: [ "$letters", "$$size"] }
        } }    
    } }
])

答案 1 :(得分:2)

最后,在吹了我的脑海后,诀窍很简单:

Aggregation agg = Aggregation.newAggregation(
Aggregation.project()
.andInclude("doc1","field1","field2")
.andExpression("slice(doc1, size(doc1)-1)").as("doc1_without_last"),
new OutOperation("newCollection")
                ).withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build());

投影中的andExpression用于包含一些String格式的mongo运算符。