MongoDB:从不同字段的不同文档返回数据的单个查找请求
我有这个收藏:MongoDB:从不同字段的不同文档返回数据的单个查找请求,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有这个收藏: { "name": "Leonardo", "height": "180", "weapon": "sword", "favorite_pizza": "Hawai" }, { "name": "Donatello", "height": "181", "weapon": "stick", "favorite_pizza": "Pepperoni" }, { "name": "Michelangelo",
{
"name": "Leonardo",
"height": "180",
"weapon": "sword",
"favorite_pizza": "Hawai"
},
{
"name": "Donatello",
"height": "181",
"weapon": "stick",
"favorite_pizza": "Pepperoni"
},
{
"name": "Michelangelo",
"height": "182",
"weapon": "nunchucks",
"favorite_pizza": "Bacon"
},
{
"name": "Raphael",
"height": "183",
"weapon": "sai",
"favorite_pizza": "Margherita"
}
使用一个查询,我希望得到以下结果(按高度排序):
因此,查询首先需要获取具有最小高度字段的文档,然后获取该文档的所有内容,然后需要获取所有其他文档并仅返回这些文档的名称字段,在按高度排序这些文档时。将高度更改为数字以正确排序,您可以尝试在3.4管道中的聚合下方进行排序 查询
$按“高度”升序排序
文档,然后按$组
创建两个字段,“第一个”字段具有最小的高度记录($$ROOT
以访问整个文档)和“所有名称”以记录所有名称
$project
使用$slice
+$concatarray
以最小高度文档替换“allnames”数组第一个元素,并获取更新的数组
使用$replaceRoot
将所有文档升级到顶层
db.colname.aggregate([
{"$sort":{
"height":1
}},
{"$group":{
"_id":null,
"first":{"$first":"$$ROOT"},
"allnames":{"$push":{"name":"$name"}}
}},
{"$project":{
"data":{"$concatArrays":[["$first"],{"$slice":["$allnames",1,{"$size":"$allnames"}] } ]}
}},
{"$unwind":"$data"},
{"$replaceRoot":{"newRoot":"$data"}}
])
将您的高度更改为数字以进行正确排序,您可以尝试在3.4管道中的聚合下方进行排序 查询
$按“高度”升序排序
文档,然后按$组
创建两个字段,“第一个”字段具有最小的高度记录($$ROOT
以访问整个文档)和“所有名称”以记录所有名称
$project
使用$slice
+$concatarray
以最小高度文档替换“allnames”数组第一个元素,并获取更新的数组
使用$replaceRoot
将所有文档升级到顶层
db.colname.aggregate([
{"$sort":{
"height":1
}},
{"$group":{
"_id":null,
"first":{"$first":"$$ROOT"},
"allnames":{"$push":{"name":"$name"}}
}},
{"$project":{
"data":{"$concatArrays":[["$first"],{"$slice":["$allnames",1,{"$size":"$allnames"}] } ]}
}},
{"$unwind":"$data"},
{"$replaceRoot":{"newRoot":"$data"}}
])
只是出于完整性的原因 @Veeram的答案可能是更好的选择(我觉得它应该更快更容易理解),但您可以使用稍微简单的
$group
阶段,然后再使用稍微复杂的$project
阶段$reduce
来实现相同的结果:
collection.aggregate([{
$sort: {
"height": 1
}
}, {
$group: {
"_id":null,
"allnames": {
$push: "$$ROOT"
}
}
}, {
$project: {
"data": {
$reduce: {
input: "$allnames",
initialValue: null,
in: {
$cond: [{
$eq: [ "$$value", null ] // if it's the first time we come here
},
[ "$$this" ], // we include the entire document
{
$concatArrays: [ // else we concat
"$$value", // the already concatenated values
[ { "name": "$$this.name" } ] // with the "name" of the currently looked at document
]
}]
}
}
}
}
}, {
$unwind: "$data"
}, {
$replaceRoot: {
"newRoot": "$data"
}
}])
或者,@Veeram在下面的评论中指出,$reduce可以这样写:
$project: {
"data": {
$reduce: {
input: { "$slice": [ "$allnames", 1, { $size: "$allnames" } ] }, // process everything in the "allnames" array except for the first item
initialValue: { "$slice": [ "$allnames", 1 ] }, // start with the first item
in: { $concatArrays: [ "$$value", [ { "name": "$$this.name" } ] ]} // and keep appending the "name" field of all other items only
}
}
}
只是出于完整性的原因 @Veeram的答案可能是更好的选择(我觉得它应该更快更容易理解),但您可以使用稍微简单的
$group
阶段,然后再使用稍微复杂的$project
阶段$reduce
来实现相同的结果:
collection.aggregate([{
$sort: {
"height": 1
}
}, {
$group: {
"_id":null,
"allnames": {
$push: "$$ROOT"
}
}
}, {
$project: {
"data": {
$reduce: {
input: "$allnames",
initialValue: null,
in: {
$cond: [{
$eq: [ "$$value", null ] // if it's the first time we come here
},
[ "$$this" ], // we include the entire document
{
$concatArrays: [ // else we concat
"$$value", // the already concatenated values
[ { "name": "$$this.name" } ] // with the "name" of the currently looked at document
]
}]
}
}
}
}
}, {
$unwind: "$data"
}, {
$replaceRoot: {
"newRoot": "$data"
}
}])
或者,@Veeram在下面的评论中指出,$reduce可以这样写:
$project: {
"data": {
$reduce: {
input: { "$slice": [ "$allnames", 1, { $size: "$allnames" } ] }, // process everything in the "allnames" array except for the first item
initialValue: { "$slice": [ "$allnames", 1 ] }, // start with the first item
in: { $concatArrays: [ "$$value", [ { "name": "$$this.name" } ] ]} // and keep appending the "name" field of all other items only
}
}
}
您可以将reduce简化为
{$reduce:{input:{“$slice”:[“$allnames”,1,{“$size”:“$allnames”}},初始值:{“$slice”:[“$allnames”,1]},在:{$concatarray:[“$$value”,[{“name”:“$$this.name”}]}}}
您可以简化为{$reduce input:{$slice:{input:{$slice[“$allnames”:,1,{“$size”:“$allnames”}]},初始值:{“$slice”:[“$allnames”,1]},位于:{$concatarray:[“$$value”,[{“name”:“$$this.name”}]}}}}