【问题标题】:Wait for a query in MongoDB在 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();

【问题讨论】:

    标签: javascript typescript mongodb


    【解决方案1】:

    Aggregate 是同步的并返回一个AggregationCursor

    游标有许多异步方法来检索实际数据:toArrayforEach 或简单的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 抽出宝贵时间回复。
    猜你喜欢
    • 2019-04-02
    • 2023-03-07
    • 2018-05-02
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 2021-06-26
    • 2019-07-04
    相关资源
    最近更新 更多