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

Mongodb聚合:投影一个没有最后一个元素的数组,mongodb,aggregation-framework,aggregation,mongodb-java,spring-mongodb,Mongodb,Aggregation Framework,Aggregation,Mongodb Java,Spring Mongodb,使用spring数据中的聚合管道,我有嵌套数组的文档,我想投影一个数组,但最后一项除外。 例如,对于每个文档,如: { "_id" : ObjectId("59ce411c2708c97154d13150"), "doc1" : [ { "nodeValue" : "AAA" }, { "nodeValue" : "BBB" }, {

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

{
    "_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,
}
我尝试了类似的方法,但没有找到一个操作符可以$pop数组并从中删除最后一项

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());

感谢您的帮助

shell查询可以如下所示:

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

如果spring中存在任何不允许您构建此类查询的限制,您可以使用以下查询变量:

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

最后,在我大吃一惊之后,诀窍很简单:

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());

投影中的
和expression
用于以字符串格式包含一些mongo运算符。

那里有一个
$slice
$slice
仅控制要投影的数组的项数
$slice(-n)
仅投影最后n个元素,而
$slice(n)
仅投影前n个元素。但是如何投影除最后一个之外的所有数组数据。对不起,忘了提到还有
$size
。除了最后一个之外,所有的都是
$slice($size-1)
。以防万一,java中管道
$slice
中的spring数据只能获取一个数值整数参数,这是无法做到的。我的想法是将数组反转,只将最后一个数组作为第一个数组,如下所示
。和(ArrayOperators.arrayOf(doc1.reverse()).as(“Reversed\u doc1
)但是如何从项目中排除
反向_doc1.0.nodeValue
。我非常确定您可以使用服务器端计算的
$size-1
构建自定义$slice,请参阅以获取灵感谢谢Alex的帮助,我尝试了类似的方法:
和(VariableOperators.define>)(VariableOperators.Let.ExpressionVariable.newVariable(“SSIZE”).forExpression(AggregationFunctionExpressions.SUBTRACT.of(Fields.field(“pathLengthInInteraction”),1)))和应用(ArrayOperators.Slice.sliceArrayOf(“doc”).offset(?)作为(“无最后一个”)
”pathLengthInInteraction是一个已投影的大小,偏移函数仅支持整数值,我无法恢复
SSIZE