跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • MongoDB 的 cursor 到底是怎么工作的?
未分類
18 1 月 2021

MongoDB 的 cursor 到底是怎么工作的?

MongoDB 的 cursor 到底是怎么工作的?

資深大佬 : JasonLaw 5

首先使用以下代码初始化 collection

db.collection.drop() for (i = 0; i < 100; i++) {  db.collection.insertOne({x: Math.floor(i/5)}); } 

然后执行var cursor = db.collection.find().batchSize(5).sort({x: 1})获取到 cursor,执行cursor.next()5 次,在执行第六次之前,执行db.collection.insertOne({x: 0}),这时执行cursor.next()的结果为{x: 1}。

我的疑问

为什么cursor.next()的结果不是{x: 0}呢? cursor 到底是怎么工作的?它是怎么决定下次 batch 应该取哪些数据的呢?

相关资料

  • What is a Cursor in MongoDB? – Stack Overflow
大佬有話說 (6)

  • 資深大佬 : yagamil

    sort 出来的是一个索引数据 temp_index,指向的你排序好的的数据,你后面再插入,不会改变之前 sort 的 temp_index
    或者用一个更加简单的例子, 先 find(), 然后插入,再用 cursor next 到最后,看会不会找到你新插入的数据

  • 主 資深大佬 : JasonLaw

    @yagamil #1

    1. 我怎么查看 temp_index 呢?这个 temp_index 是特定于这个 cursor 的吗?会有一个类似 offset 的东西记录下次应该读取的位置吗?有没有相关的资料讲这个的?我找了好久都没有找到。
    2. 我不是很理解“先 find(), 然后插入,再用 cursor next 到最后,看会不会找到你新插入的数据”。能够具体解释一下吗?

  • 主 資深大佬 : JasonLaw

    @yagamil #1

    1. 我在附言 1 描述了“使用 sort 和没有使用 sort 的区别”。使用了 sort 相当于需要在内存临时存储整个结果集吗?那么不是完全违背了使用 cursor 的初衷?
    2. 在没有使用 sort 时,它是怎么决定下次 batch 应该获取到哪些数据的呢?在 primary index 上记录 cursor 的 offset 吗?

  • 資深大佬 : leopod1995

    > 1. 我在附言 1 描述了“使用 sort 和没有使用 sort 的区别”。使用了 sort 相当于需要在内存临时存储整个结果集吗?那么不是完全违背了使用 cursor 的初衷?

    因为你 sort 的 key 是 x 是没有建立索引的,所以才会需要在内存进行排序。
    如何复现-> 给 x 加上索引,sort 的行为会保持一致。
    > 2. 在没有使用 sort 时,它是怎么决定下次 batch 应该获取到哪些数据的呢?在 primary index 上记录 cursor 的 offset 吗?
    没有使用 sort,取决于你的 query 。如果是例子中的 sql,会默认全表扫,也就是根据_id 。

    ### 总结
    你的问题主要是不知道 Mongodb 的查询原理,建议多学习查询计划,或者多看源码。
    mongodb 有个很重要的概念叫做 stage,`query`,’sort’,’fetch’都只是查询里面的一个 stage

  • 主 資深大佬 : JasonLaw

    @leopod1995 #4 谢谢你的回复。猜到应该是这样的,不过还没有看到查询计划那块,接下来看看。

  • 資深大佬 : muzuiget

    你的代码有两个问题。前提是你要知道 MongoDB 的数据是在另外一个进程里的,对你的程序来说,它就是一个服务器。

    回到 cursor 问题,cursor 可以是一“会状态为了有个现实例子,快递站跟你说你有 10 个包要收,但是你家里只能存放 1 个包了,不能一次收下,等你先处理一个包,然后再收下一个,cursor.next() 就是服务器向你发下一条记录的意思。再假设你处理了两个包后,余下的 8 个包不想要了,直接退货,那么快递站不会再给你派送了,类似有 cursor.close() 余下的条目不要了。如果你的内存足够大,能有一次过收发所有记录,那 cursor 也有 toArray() 这种方法。

    第二个问题,你的测试代码,你用 await 了吗,据我所知,MongoDB 的 NodeJS 接口都是异步了,调用函数后,未必马上执行对应的操作。

    再说,枚举一个数组类型的容器过程时,就不应该同时修改该对象的元素长度,这样太容易出现不可预测的状态错误,你要仔细看相关文档看看这样做是否安全。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具