Javascript Node.js mongodb驱动程序异步/等待查询

Javascript Node.js mongodb驱动程序异步/等待查询,javascript,node.js,mongodb,mongoose,async-await,Javascript,Node.js,Mongodb,Mongoose,Async Await,我有一个使用mongodb本机驱动程序的node.js应用程序。 在使用NodeV8.9.1将应用程序代码迁移到async/await的过程中,我正在努力为mongodb查询找到一种优雅的方法。 mongodb驱动程序的主要问题是,所有查询都使用回调,而异步方法必须使用承诺函数 备选方案: mongoose-承诺不推荐使用查询,它强制使用模式模型,这对我的应用程序来说有点开销 mongoist-据说很棒,因为它在构建时考虑了异步/等待,并且完全承诺,但是与mongodb的SSL连接错误和糟糕的

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

备选方案:

  • mongoose-承诺不推荐使用查询,它强制使用模式模型,这对我的应用程序来说有点开销
  • mongoist-据说很棒,因为它在构建时考虑了异步/等待,并且完全承诺,但是与mongodb的SSL连接错误和糟糕的文档-让我远离了这个解决方案
我以优雅的方式成功实现的唯一解决方法是使用callback promisenpm包将mongodb驱动程序API转换为fully promise


对于优雅的高性能方式有什么新的想法吗

如果您没有通过回调,mongodb客户端将返回一个承诺

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

从官方
谢谢。与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);
}))

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

UPD由美国邮政提供: 对于一般情况,使用toArray()的答案就足够了

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

对于这些情况,您可以使用MongoDB streams,它工作得很好,但比使用streams更简单的是:

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);
}
const cursor = db.collection('someCollection').find({})
for (let doc = await cursor.next(); doc; doc = await cursor.next()) {
    // Process the document.
}

编辑:“mongodb”v3.x

据 你可以用这种方式

让MongoClient=require('mongodb')。MongoClient;
常量连接字符串=mongodb://localhost:27017';
(异步()=>{
让客户端=等待MongoClient.connect(connectionString,
{useNewUrlParser:true});
设db=client.db('dbName');
试一试{
const res=await db.collection(“collectionName”).updateOne({
“someKey”:someValue
},{$set:someObj},{upsert:true});
log(`res=>${JSON.stringify(res)}`);
}
最后{
client.close();
}
})()
.catch(err=>console.error(err));

我将此作为答案发布,因为我无法对此发表评论。我一到50岁就会提出这个问题

不要忘记关闭数据库连接。否则,您的应用程序可能无法连接到数据库,因为打开的连接太多(一周前发生在我身上)

您的查询可能成功或失败,因此在
finally
块中关闭连接是有意义的

const db = await MongoClient.connect(url);
try {
    const stuff = await db.collection("Stuff").find({});
    // Do something with the result of the query
} finally {
    db.close();
}
更新:这似乎也没有解决我的问题。有些人说你甚至不需要手动关闭连接。如果可能的话,最好在整个应用程序中重用您的连接

使用异步/等待的mongoose查找查询

    var router = require("express").Router()
    var mongoose = require("mongoose")
var await = require("await")
var async = require("async")

    var mongoUrl = "mongodb://localhost:27017/ekaushalnsdc"

    router.get("/async/await/find",async(req, res,  next) => {
      try {
        var db =  await mongoose.createConnection(mongoUrl)
          var colName = db.collection('collectionName')
        var result  = await colName.find({}).toArray()
        res.json(result)
    }catch(ex) {
       res.json(ex.message)
    }
    })
在异步/等待的情况下,不要使用
mongoose.connect

    var router = require("express").Router()
    var mongoose = require("mongoose")
var await = require("await")
var async = require("async")

    var mongoUrl = "mongodb://localhost:27017/ekaushalnsdc"

    router.get("/async/await/find",async(req, res,  next) => {
      try {
        var db =  await mongoose.createConnection(mongoUrl)
          var colName = db.collection('collectionName')
        var result  = await colName.find({}).toArray()
        res.json(result)
    }catch(ex) {
       res.json(ex.message)
    }
    })

这是我发现的与Mongo3和async/await兼容的最小代码段。 享受吧

(基于Pax Beach的答案。它被否决了,我想添加一条评论,解释为什么在某些情况下,Pat的答案是最好的。我没有足够的代表添加评论。)

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

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

对于这些情况,您可以使用MongoDB streams,它工作得很好,但比使用streams更简单的是:

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);
}
const cursor = db.collection('someCollection').find({})
for (let doc = await cursor.next(); doc; doc = await cursor.next()) {
    // Process the document.
}

由于所有答案都缺少一些位(catch块,检查客户机是否为
null
),因此我提供了自己的解决方案。使用Mongo服务器v4.0.7和节点JS驱动程序3.2.2进行测试

请注意,该示例是一个控制台程序,我们在
finally
块中关闭与服务器的连接。在web应用程序中,连接被重用。 看见此外,这些错误是通过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();
    }
}

await findOne();

我正在尝试使用mongojs从mongodb获取数据,并在graphiql服务器中显示。我用承诺,终于得到了

async resolve(parent,args){
                function getdata(){
                return new Promise(function(resolve,reject){
                    var o_id = ObjectId(args.id);
                    var obj = {_id:o_id}
                    db.book.find(obj,(err,data) => {
                        if(err){
                            console.log(err);
                            reject("error in sending the book data");
                            }
                        else{
                                if(data.length>0){
                                   resolve(data);
                                }else{reject("data length is ! > 0")}
                        }
                    });
                })
                }
                async function calldata(){
                    var dataNew = await getdata().then(function(returnedData){
                        return returnedData;
                    }).catch(function(errorinpassing){
                        console.log(errorinpassing);
                    })
                    return dataNew
                }
                var hello = await calldata()
                if(hello.length>0){
                    return hello[0]
                }
            }

我来这里是为了
async/await
解决方案,但我并不喜欢任何答案,所以我想出了下面的代码片段

我使用的是本机驱动程序,效果很好。我发现它比
for
循环更具可读性:

const cursor=await db.collection('myCollection').find({});
while(等待cursor.hasNext()){
const doc=wait cursor.next();
//做什么都行。
控制台日志(doc);
};

toArray()
方法也可以,但正如前面指出的那样,您必须确保永远不会得到占用RAM的大型结果集。

@MikaS is似乎需要一个“co”包。我基本上是在寻找一个充满希望的本土图书馆这是一个很好的答案。对于任何试图找出
require('middleware')
步骤的人来说,这里有一个很好的指南:这也不起作用了。有更新的机会吗?我忽略了mongodb,现在正在使用mongoose。这是强烈推荐,因为很多更新和承诺支持。这是美丽的,正是我所寻找的。非常感谢。从版本3开始,MongoClient返回的是客户机,而不是db对象!这不管用了。我们可以获得mongodb最新版本的更新吗?假设我们在调用的函数中调用了3个以上的函数