MongoDB:单个查找请求,用于从具有不同字段的不同文档返回数据

时间:2018-01-08 15:58:08

标签: mongodb aggregation-framework

我有这个系列:

{
    "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"
}

使用一个查询我想要这个结果(按高度排序):

{
    "name": "Leonardo",
    "height": "180",
    "weapon": "sword",
    "favorite_pizza": "Hawai"
},
{
    "name": "Donatello",
},
{
    "name": "Michelangelo",
},
{
    "name": "Raphael",
}

因此查询需要首先获取具有最小高度字段的文档然后获取该文档的所有内容,然后它需要获取所有其他文档并仅返回那些文档的名称字段,同时按高度排序这些文档。

2 个答案:

答案 0 :(得分:2)

将高度更改为数字以进行正确排序,您可以在3.4管道中尝试以下聚合。

查询$sorts文档按“高度”升序后跟$group创建两个字段,“first”字段具有最小高度记录($$ROOT以访问整个文档)和“allnames”记录所有名字。

$project使用$slice + $concatArrays将“allnames”数组替换为具有最小高度文档的第一个元素,并获取更新后的数组。

<$unwind $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"}} ]) 将所有文档提升到最高级别。

    $scope.objects = [
{id: 1, name: "ma route angulaire1", cote: "10.5", style: "jungle", centre: "supercentre", img: "x"},
{id: 2, name: "ma route angulaire2", cote: "10.5", style: "jungle", centre: "supercentre", img: "x"},
{id: 3, name: "ma route angulaire3", cote: "10.5", style: "jungle", centre: "supercentre", img: "x"}
];

答案 1 :(得分:0)

只是出于完整性原因......

@ Veeram的答案可能是更好的选择(我觉得它应该更快更容易理解)但是你可以使用稍微简单的$group阶段然后稍微复杂{{1}来实现相同的结果使用$project

的舞台
$reduce

或者 - 正如@Veeram在下面的评论中所指出的那样,可以用这种方式写出$ 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"
    }
}])