Javascript 在 Node.js 中进行同步 MongoDB 查询的正确方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12030248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:56:53  来源:igfitidea点击:

What is the right way to make a synchronous MongoDB query in Node.js?

javascriptnode.jsmongodbsynchronous

提问by Mike Pateras

I'm using the Node.JS driver for MongoDB, and I'd like to perform a synchronous query, like such:

我正在为 MongoDB 使用 Node.JS 驱动程序,我想执行一个同步查询,如下所示:

function getAThing()
{
    var db = new mongo.Db("mydatabase", server, {});

    db.open(function(err, db)
    {
        db.authenticate("myuser", "mypassword", function(err, success)
        {
            if (success)
            {
                db.collection("Things", function(err, collection)
                {
                    collection.findOne({ name : "bob"}, function(err, thing)
                    {                           
                        return thing;
                    });
                });
            }
        });
    });
}

The problem is, db.open is an asychronous call (it doesn't block), so the getAThing returns "undefined" and I want it to return the results of the query. I'm sure I could some sort of blocking mechanism, but I'd like to know the right way to do something like this.

问题是,db.open 是一个异步调用(它不会阻塞),所以 getAThing 返回“未定义”,我希望它返回查询的结果。我确信我可以采用某种阻止机制,但我想知道做这样的事情的正确方法。

采纳答案by JohnnyHK

There's no way to make this synchronous w/o some sort of terrible hack. The right way is to have getAThingaccept a callback function as a parameter and then call that function once thingis available.

没有办法在没有某种可怕的黑客攻击的情况下使这种同步。正确的方法是getAThing接受一个回调函数作为参数,然后在该函数thing可用时调用该函数。

function getAThing(callback)
{
    var db = new mongo.Db("mydatabase", server, {});

    db.open(function(err, db)
    {
        db.authenticate("myuser", "mypassword", function(err, success)
        {
            if (success)
            {
                db.collection("Things", function(err, collection)
                {
                    collection.findOne({ name : "bob"}, function(err, thing)
                    {       
                        db.close();                    
                        callback(err, thing);
                    });
                });
            }
        });
    });
}

Node 7.6+ Update

节点 7.6+ 更新

async/awaitnow provides a way of coding in a synchronous stylewhen using asynchronous APIs that return promises (like the native MongoDB driver does).

async/await现在提供了一个同步编码的方式风格使用异步API,这些API返回的承诺(如本地的MongoDB驱动程序一样)时。

Using this approach, the above method can be written as:

使用这种方法,上面的方法可以写成:

async function getAThing() {
    let db = await mongodb.MongoClient.connect('mongodb://server/mydatabase');
    if (await db.authenticate("myuser", "mypassword")) {
        let thing = await db.collection("Things").findOne({ name: "bob" });
        await db.close();
        return thing;
    }
}

Which you can then call from another asyncfunction as let thing = await getAThing();.

然后您可以从另一个async函数调用它作为let thing = await getAThing();.

However, it's worth noting that MongoClientprovides a connection pool, so you shouldn't be opening and closing it within this method. Instead, call MongoClient.connectduring your app startup and then simplify your method to:

然而,值得注意的是它MongoClient提供了一个连接池,所以你不应该在这个方法中打开和关闭它。相反,MongoClient.connect在您的应用程序启动期间调用,然后将您的方法简化为:

async function getAThing() {
    return db.collection("Things").findOne({ name: "bob" });
}

Note that we don't call awaitwithin the method, instead directly returning the promise that's returned by findOne.

请注意,我们不在await方法内调用,而是直接返回由findOne.

回答by Amol M Kulkarni

ES 6(Node 8+)

ES 6(节点 8+)

You can utilize async/await

您可以使用异步/等待

awaitoperator pauses the execution of asynchronous function until the Promise is resolved and returns the value.

awaitoperator 暂停异步函数的执行,直到 Promise 被解析并返回值。

This way your code will work in synchronous way:

这样您的代码将以同步方式工作:

const query = MySchema.findOne({ name: /tester/gi });
const userData = await query.exec();
console.log(userData)





较旧的解决方案 - 2013 年 6 月;)

Now the Mongo Syncis available, this is the right way to make a synchronous MongoDB query in Node.js.

现在Mongo Sync可用了,这是在 Node.js 中进行同步 MongoDB 查询的正确方法。

I am using this for the same. You can just write sync method like below:

我也在用这个。您可以编写如下同步方法:

var Server = require("mongo-sync").Server;
var server = new Server('127.0.0.1');
var result = server.db("testdb").getCollection("testCollection").find().toArray();
console.log(result);

Note: Its dependent on the node-fiberand some issues are there with it on windows 8.

注意:它依赖于节点光纤,并且在 Windows 8 上存在一些问题。

Happy coding :)

快乐编码:)

回答by Hugheth

While it's not strictly synchronous, a pattern I've repeatedly adopted and found very useful is to use coand promisifyyield on asynchronous functions. For mongo, you could rewrite the above:

虽然它不是严格同步的,但我反复采用并发现非常有用的一种模式是在异步函数上使用copromisifyyield。对于 mongo,您可以重写上述内容:

var query = co( function* () {

    var db = new mongo.Db("mydatabase", server, {});
    db = promisify.object( db );
    db = yield db.open();

    yield db.authenticate("myuser", "mypassword");

    var collection = yield db.collection("Things");
    return yield collection.findOne( { name : "bob"} );

});

query.then( result => {

} ).catch( err => {

} );

This means:

这意味着:

  1. You can write "synchronous"-like code with any asynchronous library
  2. Errors are thrown from the callbacks, meaning you don't need the success check
  3. You can pass the result as a promise to any other piece of code
  1. 您可以使用任何异步库编写类似“同步”的代码
  2. 错误是从回调中抛出的,这意味着您不需要成功检查
  3. 您可以将结果作为承诺传递给任何其他代码