Mongodb 聚合:投影一个没有最后一个元素的数组
Mongodb Aggregation : Project an array without the last element
在 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 中有任何限制不允许您构建此类查询,您可以使用 $let 来使用查询变量:
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());
投影中的 andExpression
用于包含一些 mongo 字符串格式的运算符。
在 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 中有任何限制不允许您构建此类查询,您可以使用 $let 来使用查询变量:
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());
投影中的 andExpression
用于包含一些 mongo 字符串格式的运算符。