【问题标题】:MongoDB - sort by subdocument matchMongoDB - 按子文档匹配排序
【发布时间】:2014-02-10 03:47:14
【问题描述】:

假设我在 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,我就不能再利用索引来匹配或排序集合,这使得该解决方案对于非常大的集合有些不可行。

【问题讨论】:

    标签: mongodb sorting


    【解决方案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
    }
    

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

    【讨论】:

    • 正是我最终所做的 :) 感谢您重申它。关于第二个建议 - 不幸的是,索引太多不同的“特征”(MongoDB 目前允许每个集合最多 64 个不同的索引)。
    猜你喜欢
    • 2013-10-21
    • 2014-06-23
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    • 2015-07-23
    • 1970-01-01
    相关资源
    最近更新 更多