Ich habe eine node.js-Anwendung, die den mongodb-Treiber verwendet. Beim Migrieren meines Anwendungscodes nach async/await mit Knoten v8.9.1 bemühe ich mich, einen eleganten Weg für die mongodb-Abfragen zu finden. Das Hauptproblem des mongodb-Treibers ist, dass alle Abfragen Rückrufe verwenden, bei denen Versprechungsfunktionen für die asynchronen Methoden obligatorisch sind.
Alternativen:
Die einzige Problemumgehung, die ich auf elegante Weise implementieren konnte, ist die Verwendung des callback-promise npm-Pakets, um die mongodb-Treiber-API vollständig zu konvertieren.
Irgendwelche frischen Ideen für einen eleganten Hochleistungsweg?
Dies ist der kleinste Code, den ich gefunden habe und der mit Mongo3 und Async/await kompatibel ist.
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();
}
}
}
Edit: 'mongodb' v3.x
gemäß mongoDB ES6 future Sie können diesen Weg verwenden;
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));
Vielen Dank. Arbeitet gut mit 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);
}))
Da bei allen Antworten einige Bits fehlen (catch-Blöcke, überprüfen, ob der Client nicht null
ist), habe ich meine eigene Lösung entwickelt. Getestet mit Mongo Server v4.0.7 und Node JS driver 3.2.2.
Beachten Sie, dass es sich bei dem Beispiel um ein Konsolenprogramm handelt, bei dem die Verbindung zum Server im Block finally
getrennt wird. In einer Webanwendung werden die Verbindungen wiederverwendet. Siehe Node Mongo-Dokumente . Außerdem werden die Fehler mit Bibliotheken wie Winston oder Morgan und nicht mit der Konsole protokolliert.
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();
Ich poste dies als Antwort, da ich die Antwort von Ido Lev nicht kommentieren kann. Ich werde dies umziehen, sobald ich 50 Reputation erreicht habe.
Vergessen Sie nicht, die Datenbankverbindung zu schließen. Andernfalls ist es möglich, dass Ihre Anwendung aufgrund zu vieler offener Verbindungen keine Verbindung zur Datenbank herstellen kann (ist mir vor einer Woche passiert).
Ihre Abfrage kann erfolgreich sein oder fehlschlagen, daher ist es sinnvoll, die Verbindung in einem finally
- Block zu schließen.
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();
}
Update: Es scheint, dass dies auch mein Problem nicht behoben hat. Einige Leute sagen, dass Sie die Verbindung nicht einmal manuell trennen müssen. Es scheint, dass es am besten ist, wenn möglich, die Verbindung in Ihrer Anwendung erneut zu verwenden.
Wenn Sie keinen Rückruf übergeben, gibt der mongodb-Client ein Versprechen zurück.
Der offizielle MongoDB Node.js-Treiber bietet sowohl auf Callback basierende als auch auf Promised basierende Interaktion mit MongoDB, sodass Anwendungen die neuen Funktionen von ES6 voll ausnutzen können
Aus den offiziellen docs
mongoose find Query mit async/await
verwenden Sie nicht mongoose.connect
im Falle von async/await
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)
}
})
Wenn Sie mit dem Cursor arbeiten möchten, ohne das Array zu entladen, können Sie waitit nicht mit find () oder aggregate () - Funktionen verwenden. Dann müssen Sie den Code verwenden:
UPD von Usas: Für den allgemeinen Fall sind die Antworten mit toArray () ausreichend.
Bei umfangreichen Dokumentensammlungen würde jedoch die Verwendung von toArray () den verfügbaren Arbeitsspeicher übersteigen. Eine "Hochleistungs" -Lösung in diesen Situationen darf daher nicht für array () verwendet werden.
In diesen Fällen können Sie MongoDB-Streams verwenden, was gut funktioniert, aber noch einfacher als das Verwenden von 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);
}
(Basierend auf der Antwort von Pax Beach. Es wurde abgelehnt, und ich wollte einen Kommentar hinzufügen, in dem erklärt wird, warum Pats Antwort in manchen Situationen die beste ist.
Für den allgemeinen Fall sind die Antworten mit toArray () ausreichend.
Wenn jedoch riesige Dokumentensammlungen involviert sind, würde die Verwendung von toArray () den verfügbaren Arbeitsspeicher übersteigen. Eine "Hochleistungs" -Lösung in diesen Situationen darf daher nicht für array () verwendet werden.
In diesen Fällen können Sie MongoDB-Streams verwenden, was gut funktioniert, aber noch einfacher als das Verwenden von Streams:
const cursor = db.collection('someCollection').find({})
for (let doc = await cursor.next(); doc; doc = await cursor.next()) {
// Process the document.
}