代码之家  ›  专栏  ›  技术社区  ›  phatmanace

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

  •  0
  • phatmanace  · 技术社区  · 12 年前

    如果我有这个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 回复  |  直到 9 年前
        1
  •  1
  •   Neil Lunn    12 年前

    正如您注意到的操作,如 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 行动。