MongoDB - 按子文档匹配排序

时间:2014-02-09 18:23:28

标签: mongodb sorting

说我在MongoDB中有一个users集合。典型的用户文档包含名称字段和表示用户特征的子文档数组。说这样的话:

{   
    "name": "Joey",
    "characteristics": [
        {
            "name": "shy",
            "score": 0.8
        },
        {
            "name": "funny",
            "score": 0.6
        },
        {
            "name": "loving",
            "score": 0.01
        }
    ]
}

我怎样才能找到最有趣的X用户,根据它们的有趣程度排序?

到目前为止,我找到的唯一方法是使用聚合框架,在类似的查询中:

db.users.aggregate([
    {$project: {"_id": 1, "name": 1, "characteristics": 1, "_characteristics": '$characteristics'}},
    {$unwind: "$_characteristics"},
    {$match: {"_characteristics.name": "funny"}},
    {$sort: {"_characteristics.score": -1}},
    {$limit: 10}
]);

这似乎正是我想要的,除了根据MongoDB's documentation on using indexes in pipelines的事实,一旦我在聚合管道中调用$project$unwind,我就不能再使用索引了匹配或排序集合,这使得这个解决方案对于非常大的集合来说有些不可行。

1 个答案:

答案 0 :(得分:1)

我认为你已到了一半。我会做的

db.users.aggregate([
  {$match: { 'characteristics.name': 'funny' }},
  {$unwind: '$characteristics'},
  {$match: {'characteristics.name': 'funny'}},
  {$project: {_id: 0, name: 1, 'characteristics.score': 1}},
  {$sort: { 'characteristics.score': 1 }},
  {$limit: 10}
])
  • 我添加了一个match阶段,以摆脱没有funny属性(可以轻松编入索引)的用户。
  • unwindmatch再次仅保留数据的某一部分
  • 仅使用project
  • 保留必要的数据
  • sort正确分数
  • limit结果。

这样你可以使用索引进行第一场比赛。

我看待它的方式,如果您感兴趣的特征不是太多,IMO最好将您的结构设为

{  
    "name": "Joey",
    "shy": 0.8
    "funny": 0.6
    "loving": 0.01
}

这样你可以使用索引(稀疏或不稀疏)来让你的生活更轻松!