【问题标题】:Mongo circle queryMongo圈子查询
【发布时间】:2014-01-29 04:29:40
【问题描述】:

我可以运行查询以获取确切的文档数量吗?

我有收藏:

> db.circle.find() {“_id”:1} {“_id”:2} {“_id”:3}

执行查询:

> db.circle.find().skip(2).limit(2) {“_id”:3}

响应 1 个文档,但我需要 2 个

查看此响应的最佳方式是什么?

{“_id”:3} {“_id”:1}

【问题讨论】:

  • 您知道skip(2) 会跳过前两个文档,因此您不会在结果中看到id 为2 的文档吗?您是否在询问如何跳过 id 为 2 的文档(如果是,$ne)。或者您是在问如何以编程方式跳过最少的数量,以便返回的文档数量正好是限制? (虽然在后一种情况下,不能保证你会得到 3 和 1。)不清楚你在问什么。
  • @RayToal 他想在skip之后拿两个,如果还不够就从头继续。因此,标题:圆形查询
  • 是的,如果剩下的不够,我想从头开始

标签: mongodb


【解决方案1】:

我找到了一种使用聚合框架在一个查询中解决此问题的方法:

result = db.circle.aggregate([
    {   
        $project: {
            virtual_id: { $ifNull: [null, [1, 2]] }
            // extra fields go here...
        }
    },
    { $unwind: '$virtual_id' },
    { $sort: { virtual_id: 1, _id: 1 } },

    { $skip: 2 },
    { $limit: 2 }   
]);

这基本上是复制数据集,将其附加到末尾,然后应用跳过和限制操作。

步骤:

  1. $projectvirtual_id 字段添加到每个文档中,并将数组[1, 2] 作为值。 $ifNull 添加具有静态值的字段的方法是我在this answer 中找到的一个不错的技巧。

  2. $unwind by virtual_id 将数据集翻倍。

  3. $sort 确保两个连接的数据集正确排序。此操作后,_id 的值将是:1, 2, 3, 1, 2, 3

  4. $skip$limit 显而易见

注 1

如果您需要检索除_id 之外的任何其他字段,则应在$project 操作中指定它们(默认检索_id)。例如,要在输出中获取 extra_fieldyet_another_field 的值,请执行以下操作:

        $project: {
            virtual_id: { $ifNull: [null, [1, 2]] },
            extra_field: 1,
            yet_another_field: 1
        }

注2

这个解决方案可能不适合非常大的数据集,因为:

  • 聚合框架的输出大小有限(我相信是 16MB)
  • $sort 操作可能很昂贵,因为不能定义任何索引来覆盖virtual_id

【讨论】:

    【解决方案2】:
    The cursor.skip() method is often expensive because it requires the server to walk from 
    the beginning of the collection or index to get the offset or skip position before 
    beginning to return result
    

    所以在您的代码中,db.circle.find().skip(2).limit(2),它将跳过前 2 个文档并返回下一个 2。 更多详情请参考cursor.skip()

    如果您想跳过具有特定 ID 的文档,请使用 $ne 运算符:

     db.circle.find({"_id":{ "$ne" : 2}})
    

    它将返回您以下文件:

    { "_id" : 3 }
    { "_id" : 1 }
    

    【讨论】:

    • 我认为在 OP 说明的特定情况下是正确的。但是,如果集合中有 6 个元素,并且他确实 skip(5),他会期望返回 ID 6 和 1
    • @w0lf :在这种情况下,skip(5) 将跳过前 5 个文档,并且仅返回 ID 6。
    • 我在描述 OP 想要什么;不是实际结果。
    【解决方案3】:

    我用db.collection.count()

    Docs:

    db.collection.count()

    返回匹配 find() 查询的文档数。这 db.collection.count() 方法不执行 find() 操作,但 而是计算并返回与查询匹配的结果数。

    【讨论】:

    • 如果我需要更多文件,我需要执行 2 个请求?
    猜你喜欢
    • 2013-02-22
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多