【问题标题】:find and count in single mongodb query在单个 mongodb 查询中查找和计数
【发布时间】:2016-08-04 10:54:42
【问题描述】:

我的文档是这样的。

{
"_id" : ObjectId("572c4bffd073dd581edae045"),
"name" : "What's New in PHP 7",
"description" : "PHP 7 is the first new major version number of PHP since 2004. This course shows what's new, and what's changed.",
"difficulty_level" : "Beginner",
"type" : "Normal",
"tagged_skills" : [ 
    {
        "_id" : "5714e894e09a0f7d804b2254",
        "name" : "PHP"
    }
],
"created_at" : 1462520831.649,
"updated_at" : 1468233074.243    }

是否可以在单个查询中获取最近的 5 个文档和总数。 我正在使用两个查询来满足这个要求,如下所示。

db.course.find().sort({created_at:-1}).limit(5)
db.course.count()

【问题讨论】:

    标签: javascript mongodb performance mongodb-query


    【解决方案1】:

    这是聚合框架的完美工作。

    db.course.aggregate(
        [
            { "$sort": { "created_at": -1 }},
            { "$group": {
                "_id": null, 
                "docs": { "$push": "$$ROOT" }, 
                "count": { "$sum": 1 }
            }},
            { "$project": { "_id": 0, "count": 1, "docs": { "$slice": [ "$docs", 5 ] } }}
        ]
    )
    

    如果您的 MongoDB 服务器不支持$slice,那么您需要使用丑陋且低效的方法。

    db.course.aggregate(
        [
            { "$sort": { "created_at": -1 }},
            { "$group": {
                "_id": null, 
                "docs": { "$push": "$$ROOT" }, 
                "count": { "$sum": 1 }
            }},
            { "$unwind": "$docs" },
            { "$limit": 5 }
        ]
    )
    

    【讨论】:

    • 你能给我解释一下$$ROOT吗?
    • @jarryjafery $$ROOT 是 MongoDB 中的一个系统变量,可让您访问正在处理的文档。当我有一点时间时,我会在我的答案中添加一个解释。
    • 为什么第二次查询效率低?
    【解决方案2】:

    您可以使用 $facet 轻松实现此功能

    myCollection.aggregate([
        {
          $facet: {
            count: [{ $count: "value" }],
            data: [{ $sort: { _id: -1 } }, { $skip: skip }, { $limit: limit }]
          }
        },
        { $unwind: "$count" },
        { $set: { count: "$count.value" } }
    ])
    

    返回结果如下:

    [
      {
        "count": 234,
        "data": [
          // ...
        ]
      }
    ]
    

    【讨论】:

      【解决方案3】:

      @styvane 我亲自测试过,这个查询比两次查询效率还要低。

      // get count 
      db.course.aggregate([{$match:{}}, {$count: "count"}]);
          // get docs
      db.course.aggregate(
             [
                  {$match:{}},
                  { "$sort": { "created_at": -1 }},
                  {"$skip": offset},
                  {"$limit": limit}
              ]
      )
      

      【讨论】:

        【解决方案4】:

        不,没有其他办法。两个查询 - 一个用于计数 - 一个有限制。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-04
          • 1970-01-01
          • 2019-02-03
          • 2021-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多