在 MongoDB 中等待查询

Posted

技术标签:

【中文标题】在 MongoDB 中等待查询【英文标题】:Wait for a query in MongoDB 【发布时间】:2022-01-19 17:20:53 【问题描述】:

我有这个用 Typescript 编写的异步方法来查询,使用 nodejs 驱动程序,一个 MongoDB;编译器指出“myConnectedClient”之前的“await”对这个表达式的类型没有影响;我很困惑:对聚合()的调用是异步的吗?所以,我必须等待吗?谢谢。

async findQuery<T>(
    collection: string,
    findParams: Query<T>,
    sort: Sort<T>,
    myConnectedClient: MongoClient
  ) 
    const firstResult = await myConnectedClient // the compiler indicates await is useless
      .db("ZZZ_TEST_ALL")
      .collection("my_collection_01")
      .aggregate<string>([ $project:  _id: 0, name: 1  ]);
    firstResult.forEach((field) => 
      console.log(`Field: $field`);
    );
  

更新:我必须在 .aggregate() 调用之后添加 .toArray();但为什么?任何人都可以解释我的机制吗?聚合()没有回调并且不返回承诺? .toArray() 有替代品吗?谢谢。

// now await it's ok
const firstResult = await myConnectedClient
      .db("ZZZ_TEST_ALL")
      .collection("my_collection_01")
      .aggregate<string>([ $project:  _id: 0, name: 1  ]).toArray();

【问题讨论】:

【参考方案1】:

Aggregate 是同步的并返回一个AggregationCursor。

游标有许多异步方法来检索实际数据:toArray、forEach 或简单的iterator

在第一个sn -p firstResult中是游标,所以不需要等待。 您使用 firstResult.forEach 来记录结果。它确实返回了承诺,但你忽略了它,这会咬你 - findQuery 返回的承诺将立即解决,而 forEach 将并行迭代结果。为了保持承诺链,你应该这样做

const firstResult = myConnectedClient.......; 
return firstResult.forEach(......);

所以从findQuery 返回的承诺只有在 forEach 被解析时才会被解析,例如你完成了对结果的迭代。

在第二个“update”sn-p中,firstResult是数据,所以需要await从toArray()中获取。显式游标的等价物是:

const cursor = myConnectedClient.......; 
const firstResult = await cursor.toArray();

【讨论】:

但是为什么 aggregate() 不是异步的?它从数据库(I/O)中检索数据,所以在我看来应该是异步的,对吧? 因为文档是这样说的。我的答案中第一个链接后面的最上面一行说:aggregate&lt;T&gt;(pipeline?: Document[], options?: AggregateOptions): AggregationCursor&lt;T&gt; 你看,它返回一个对象。异步函数总是返回一个 Promise。它是 javascript。单线程,做异步操作的唯一方法是将控制权交还给事件循环。 我认为您对瘦客户端的 I/O 操作感到困惑,例如文件 I/O、http、sql。 Mongo 略有不同。客户端相当厚实,它在启动时会打开许多​​到 mongo 实例的持久连接并管理池以方便数据传输。聚合不检索数据,但发送请求以在服务器上运行管道。 Cursor 有许多异步方法来实际检索数据,但我认为我已经在答案中提到了它。 我非常欣赏理解一切并基于这些知识构建软件的态度。这将是理想的。这种方法的根本缺陷是,在现实世界中,没有人知道一切。在某些时候,您需要划清界限并相信文档 - 如果它说它是这样工作的,测试表明它确实如此,所以它一定是它。 感谢 Alex 抽出宝贵时间回复。

以上是关于在 MongoDB 中等待查询的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的嵌套MongoDB查询

连续迭代 mongodb 游标(在移动到下一个文档之前等待回调)

连续迭代 mongodb 游标(在移动到下一个文档之前等待回调)

如何在 2 个地图函数中等待并从 mongoDB 检索文档

如何在 2 个地图函数中等待并从 mongoDB 检索文档

mongodb模糊查询语句用法