Node.js mongodb驱动程序async/await查询

Ido*_*Lev 24 javascript mongoose mongodb node.js async-await

我有一个使用mongodb本机驱动程序的node.js应用程序.在使用节点v8.9.1将我的应用程序代码迁移到async/await的过程中,我正在努力为mongodb查询找到一种优雅的方法.mongodb驱动程序的主要问题是,所有查询都使用回调,其中promises函数对于异步方法是必需的.

备择方案:

  • mongoose - promises查询已弃用,它强制使用Schema模型,这对我的应用程序来说有点开销.
  • mongoist - 据说很棒,因为它建立了async/await并且完全承诺,但SSL连接到mongodb和糟糕的文档的错误 - 使我远离这个解决方案.

我成功实现的唯一解决方法是使用callback-promise npm包将mongodb驱动程序API转换为完全承诺.

优雅高效的方式有什么新鲜的想法吗?

Ser*_*tes 29

编辑:' mongodb'v3.x

根据mongoDB ES6未来 你可以用这种方式;

let MongoClient = require('mongodb').MongoClient;
const connectionString = 'mongodb://localhost:27017';

    (async () => {
        let client = await MongoClient.connect(connectionString,
            { useNewUrlParser: true });

        let db = client.db('dbName');
        try {
           const res = await db.collection("collectionName").updateOne({ 
               "someKey": someValue
           }, { $set: someObj }, { upsert: true });

           console.log(`res => ${JSON.stringify(res)}`);
        }
        finally {
            client.close();
        }
    })()
        .catch(err => console.error(err));
Run Code Online (Sandbox Code Playgroud)

  • 这不再起作用了.我们可以获得最近版本的mongodb的更新吗? (5认同)

Ido*_*Lev 28

谢谢.与ES6一起工作:

const middleWare = require('middleWare');
const MONGO = require('mongodb').MongoClient;

router.get('/', middleWare(async (req, res, next) => {
    const db = await MONGO.connect(url);
    const MyCollection = db.collection('MyCollection');
    const result = await MyCollection.find(query).toArray();
    res.send(result);
}))
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的答案。对于试图找出“require(‘middleware’)”步骤的其他人,这里有一个很好的指南:https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8 -b8af872c0016 (2认同)

Jan*_*nar 20

由于所有答案都缺少一些内容(捕获块,请检查客户端是否不是null),因此我提供了自己的解决方案。已在Mongo服务器v4.0.7和Node JS驱动程序3.2.2中进行了测试。

注意,该示例是一个控制台程序,在该程序块中,我们关闭了与服务器的连接finally。在Web应用程序中,连接被重用。请参阅Node Mongo docs。另外,错误是使用Winston或Morgan等库记录的,而不是控制台记录的。

const MongoClient = require('mongodb').MongoClient;

const url = 'mongodb://localhost:27017';

async function findOne() {

    const client = await MongoClient.connect(url, { useNewUrlParser: true })
        .catch(err => { console.log(err); });

    if (!client) {
        return;
    }

    try {

        const db = client.db("testdb");

        let collection = db.collection('cars');

        let query = { name: 'Volkswagen' }

        let res = await collection.findOne(query);

        console.log(res);

    } catch (err) {

        console.log(err);
    } finally {

        client.close();
    }
}

findOne();
Run Code Online (Sandbox Code Playgroud)


Sov*_*Sok 11

这是我发现的与Mongo3和async/await兼容的最小代码.请享用!

module.exports = {
  myFunction: async (query) => {
    let db, client;
    try {
      client = await MongoClient.connect(process.env.MONGODB_CONNECTION_STRING, { useNewUrlParser: true });
      db = client.db(dbName);
      return await db.collection(collectionName).find(query).toArray();
    } finally {
      client.close();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,可能,我只是发现其他答案不够简洁 (2认同)

Sur*_*rya 10

如果你不传递回调,mongodb 客户端会返回一个承诺。

官方 MongoDB Node.js 驱动程序提供基于回调和基于承诺的与 MongoDB 的交互,允许应用程序充分利用 ES6 中的新功能

来自官方 文档


Pax*_*ach 6

如果您想在不卸载到数组的情况下使用游标,则不能将 await 与 find() 或 aggregate() 函数一起使用,那么您必须使用以下代码:

Usas 的 UPD: 对于一般情况,使用 toArray() 的答案就足够了。

但是当涉及大量文档集合时,使用 toArray() 会超出可用 RAM。因此,在这些情况下的“高性能”解决方案不能使用 toArray()。

对于这些情况,您可以使用 MongoDB 流,它运行良好,但比使用流更简单的是:

const cursor = db.collection('name').aggregate(
    [
        {
            "$match": {code: 10}
        },
        {
          "$count": "count"
        }
    ],
    {
        "allowDiskUse": false
    }
)

for (let doc = await cursor.next(); doc != null; doc = await cursor.next()) {
    console.log('aggregate:', doc.count);
}
Run Code Online (Sandbox Code Playgroud)

  • @Pax_Beach - 请编辑您的答案,以便我将其视为有用的。请参阅上面的美国评论。由于 Usas 对您的答案相关的极少数情况的解释,需要进行编辑(没有更改)。 (3认同)