我可以使用内置的mongo对数组元素进行排序吗?

时间:2014-02-13 22:08:54

标签: mongodb mongodb-query aggregation-framework

如果我有这个mongo文件。

{
    "_id" : ObjectId("52fd40e781ddcb34819ac21e"),
    "name" : "fred",
    "fruits_i_like" : [
        "pear",
        "apple",
        "banana"
    ]
}
{
    "_id" : ObjectId("52fd40fa81ddcb34819ac21f"),
    "name" : "barney",
    "fruits_i_like" : [
        "pear",
        "apple",
        "peach"
    ]
}

我可以对子键进行排序,以便我得到

{
    "_id" : ObjectId("52fd40e781ddcb34819ac21e"),
    "name" : "fred",
    "fruits_i_like" : [
        "apple",
        "banana",
        "pear"
    ]
}
{
    "_id" : ObjectId("52fd40fa81ddcb34819ac21f"),
    "name" : "barney",
    "fruits_i_like" : [
        "apple",
        "peach",
        "pear"
    ]
}

即 - 我并不关心文档的排序,但每次在查找光标中打印文档时,应对子项中的水果列表进行排序。我可以将自定义javascript函数传递给forEach()上的find() - 但我想知道是否有更多内置方式来构建mongo功能。

1 个答案:

答案 0 :(得分:1)

当您注意到forEach之类的操作是迭代器时,您必须对检索的每个项执行排序操作。虽然这可能适用于某些情况,但有很多原因导致这不是您想要的。特别是如果你想对内部数组中的内容进行任何有意义的过滤。

你可以在aggregation pipeline中使用数组操作做很多事情,所以要使用已排序的数组项返回结果:

db.collection.aggregate([
    // Unwind the array elements into each document
    {$unwind: "$fruits_i_like"},

    // Sort on the array key
    {$sort: { fruits_i_like: 1 }},

    // Push the elements back into an array
    {$group: { 
        _id: {_id: "$_id", name: "$name"}, 
        fruits_i_like: {$push: "$fruits_i_like"}
    }},

    // Restore the original document form
    {$project: { _id:0, _id: "$_id", name: "$_id.name", fruits_i_like: 1}}
])

因此使用$unwind 非规范化,以便您可以对内部元素执行其他操作。此外,aggregate命令在最新的驱动程序中返回一个游标,就像find一样,并且将在未来版本中内部执行此操作。

当然,如果您希望始终的文档已排序数组,请查看$sort修饰符,以便在update操作中使用。