对数组中的文档进行排序

Sorting on documents within an array

我已经非常努力地阅读了有关查找和排序的文档,但没有成功。如果它不适合我想做的操作,我可以更改我的文档结构,但我更喜欢我当前的结构。

所有用户都有名字和一系列技能,每个人都有名字和相关的技能水平。所有用户在每项技能上都有技能水平。

这是我的结构:

{
    "name": "Alice",
    "skills": [
        {
            "name": "gardening",
            "level": 10
        },
        {
            "name": "shopping",
            "level": 7
        }
    ]
},
{
    "name": "Bruce",
    "skills": [
        {
            "name": "gardening",
            "level": 5
        },
        {
            "name": "shopping",
            "level": 10
        }
    ]
}

我有很多这样的对象,我将它们中的每一个都称为 Users。我想按园艺技能对用户进行排序 level

我知道我可以访问 10 级 Users,无论他们是 10 级的哪个技能,使用查找查询:

{ 'skills.level' : 10 }

但我想按用户的园艺技能水平对用户进行排序,排序命令如下:

{ "skills.gardening.level" : 1 }

但由于我当前的结构,这不起作用。

我是否需要更改我的结构才能像这样排序,或者我可以让它工作吗?

您可以在不更改文档结构的情况下进行这项工作,但代价是该操作不会使用索引,并且对于很多用户来说会非常慢。使用聚合框架:

> db.users.aggregate([
    { "$unwind" : "$skills" },
    { "$match" : { "skills.name" : "gardening" } }
    { "$sort" : { "skills.level" : 1 } }
])
{ "_id" : ObjectId(...), "name" : "Bruce", "skills" : { "name" : "gardening", "level" : 5 } }
{ "_id" : ObjectId(...), "name" : "Alice", "skills" : { "name" : "gardening", "level" : 10 } }

在没有关于您如何使用集合的任何其他信息的情况下,允许您按个人技能水平排序的最简单更改是重新设计文档,以便一个文档代表一个用户的一种技能:

{
    "name" : "Alice",
    "skill" : "gardening",
    "level" : 10
}

针对特定 skilllevel 排序:

db.skills.find({ "skill" : "gardening" }).sort({ "level" : 1 })

{ "skill" : 1, "level" : 1 } 上的索引。

正在检索具有与旧用户文档等效信息的文档集合:

db.skills.find({ "name" : "Alice" })

{ "name" : 1 } 上的索引。