Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB:从不同字段的不同文档返回数据的单个查找请求_Mongodb_Aggregation Framework - Fatal编程技术网

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”}]}}}}