我有一个使用mongodb本机驱动程序的node.js应用程序。 在使用节点v8.9.1将我的应用程序代码迁移到async / await的过程中,我正在努力为mongodb查询找到一种优雅的方式。 mongodb驱动程序的主要问题是,所有查询都使用回调,其中promises函数对于异步方法是必需的。
备选方案:
我成功实现的唯一解决方法是使用 callback-promise npm包将mongodb驱动程序API转换为完全承诺。
任何有关优雅高性能方式的新想法?
答案 0 :(得分:25)
编辑:' mongodb'的 3.x版强>
根据mongoDB ES6 future 你可以用这种方式;
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));
答案 1 :(得分:20)
感谢。与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);
}))
答案 2 :(得分:10)
这是我发现与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();
}
}
}
答案 3 :(得分:5)
由于所有答案都缺少一些内容(捕获块,请检查客户端是否不是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();
答案 4 :(得分:4)
我将此作为答案发布,因为我无法对Ido Lev's answer发表评论。一旦我达到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();
}
更新:这似乎也没有解决我的问题。有人说你甚至不需要手动关闭连接。如果可能的话,在您的应用程序中重用您的连接似乎是最好的。
答案 5 :(得分:3)
如果你没有通过回调,mongodb客户端会返回一个承诺。
官方MongoDB Node.js驱动程序提供基于回调和基于Promised的MongoDB交互,允许应用程序充分利用ES6中的新功能
来自官方 docs
答案 6 :(得分:3)
猫鼬使用异步/等待查找查询
不要在异步/等待的情况下使用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)
}
})
答案 7 :(得分:2)
如果你想使用游标而不卸载到Array,你不能使用await和find()或aggregate()函数,那么你必须使用代码:
Usas的UPD: 对于一般情况,使用toArray()的答案就足够了。
但是当涉及大量文档集时,使用toArray()会超出可用RAM。因此,在这些情况下,“高性能”解决方案不得使用toArray()。
对于这些情况,你可以使用MongoDB流,它运行良好,但比使用流更简单:
Won't Fix
答案 8 :(得分:1)
(基于Pax Beach的回答。它已被否决,我想添加一条评论来解释为什么在某些情况下Pat的回答是最好的。我没有足够的代表来添加评论。)
对于一般情况,使用toArray()的答案就足够了。
但是当涉及到巨大的文档集合时,使用toArray()会超出可用的RAM。因此,在这些情况下的“高性能”解决方案一定不能使用toArray()。
在这种情况下,您可以使用MongoDB流,效果很好,但比使用流更简单:
org.hibernate.type.LocalDateType - Maps a java.time.LocalDate to a Oracle DATE
org.hibernate.type.LocalDateTimeType - Maps a java.time.LocalDateTime to a Oracle TIMESTAMP
答案 9 :(得分:1)
我是来这里寻求async/await
解决方案的,但我真的不喜欢任何答案,所以我想出了以下代码段。
我正在使用本机驱动程序,并且效果很好。我发现它比for
循环更具可读性:
const cursor = await db.collection('myCollection').find({});
while (await cursor.hasNext()) {
const doc = await cursor.next();
// do whatever, ex.
console.log(doc);
};
toArray()
方法也可以,但是-如之前所指出的-您必须确保您永远不会获得占用内存的大型结果集。
答案 10 :(得分:0)
我正在尝试使用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]
}
}