2017-01-29 19 views
6

Ich baue eine Express-App, die MongoDB für ihr Backend verwendet, aber wenn ich eine Anfrage an die Datenbank in anderen Teilen der App mache, wird sie nicht erkannt.MongoDB-Treiber wird nicht erkannt

Hier ist, was ich habe:

APP.JS (Paul Antwort verwenden):

var express = require('express'); 
var app = express(); 
var bodyParser = require('body-parser'); 
var cookieParser = require('cookie-parser'); 
var passport = require('passport'); 
var mongo = require('mongodb').MongoClient; 
var assert = require('assert'); 

// make mongodb available to the application 
app.use((req, res, next) => { 
    mongo.connect('mongodb://localhost:27017/formulas', (e, db) => { 
    if (e) return next(e); 
    req.db = db; 
    next(); 
}); 

// cleanup 
    req.on('end',() => { req.db.close(); }); 
}); 

//define routes 
var root = require('./routes/index'); 
var authenticate = require('./routes/authenticate'); 
var about = require('./routes/about'); 
var contact = require('./routes/contact'); 
var formula = require('./routes/formula'); 
var formulaAPI = require('./routes/api/formula'); 
var formulaList = require('./routes/formula-list'); 
var formulaListAPI = require('./routes/api/formula-list'); 

app.set('view engine', 'ejs'); 
app.set('views', __dirname + '/views'); 
app.use(express.static(__dirname + '/public')); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: false })); 

app.use(root); 
app.use(about); 
app.use(contact); 
app.use(formula); 
app.use(formulaAPI); 
app.use(formulaList); 
app.use(formulaListAPI); 
app.use(authenticate); 

app.listen(3000, function(){ 
    console.log("The server is now listening on port 3000"); 
}); 

module.exports = app; 

Wenn ich rufen Sie die Datenbank über eine Route wie folgt aus:

var app = require('express'); 
var router = app.Router(); 
var data = require('../data/formula.json'); 

router.get('/formula-list', function(req, res){ 
var db = req.db; 
db.formulas.find({}, {}, function(e, docs){ 
    res.render('formula-list', { 
    formulas: docs, 
    title: 'Your Formulas', 
    description: `List of saved user formulas from the formula generator`, 
    ID: 'formula-list', 
    keywords: 'formula generator, health kismet, nutraceutical formula 
    builder' 
    }); 
}); 
}); 

I den folgenden Fehler erhalten:

TypeError: Cannot read property 'find' of undefined 

Wenn ich ein console.log(req.db) ich folgend in meiner Konsole erhalten:

req.db:

EventEmitter { 
domain: null, 
_events: {}, 
_eventsCount: 0, 
_maxListeners: undefined, 
s: 
{ databaseName: 'formulas', 
dbCache: {}, 
children: [], 
topology: 
    EventEmitter { 
    domain: null, 
    _events: [Object], 
    _eventsCount: 7, 
    _maxListeners: undefined, 
    clientInfo: [Object], 
    s: [Object] }, 
options: 
    { readPreference: [Object], 
    promiseLibrary: [Function: Promise] }, 
logger: { className: 'Db' }, 
bson: {}, 
authSource: undefined, 
readPreference: 
    { _type: 'ReadPreference', 
    mode: 'primary', 
    tags: undefined, 
    options: undefined }, 
bufferMaxEntries: -1, 
parentDb: null, 
pkFactory: undefined, 
nativeParser: undefined, 
promiseLibrary: [Function: Promise], 
noListener: false, 
readConcern: undefined }, 
serverConfig: [Getter], 
bufferMaxEntries: [Getter], 
databaseName: [Getter] } 
+0

Können Sie die Middleware anzeigen, die die mongoclient-Instanz an die Anfrage anfügt? – Paul

+0

@Paul - vielleicht haben Sie das Thema nur gestreift, weil es keine gibt. Ich ging davon aus, dass das Einpacken des Treibers im "App" -Export ausreichen würde, solange ich es in die Teile der App einfügte, in denen ich es aufrufen musste. –

Antwort

3

Going durch die documentation on npm, kann ich sehen, dass eine bestimmte Sammlung zugreifen zu können, ist es das, was Sie zu tun haben:

  1. die Sammlung aus, auf dem die Operation
  2. Führen Sie die Operation ausgeführt werden soll Hier

ist das Codebeispiel:

router.get('/formula-list', function(req, res) { 

    // Select the collection on which you want to perform an operation 
    var formulas = req.db.collection('formulas'); 

    // Perform that operation 
    formulas.find({}, {}, function(e, docs) { 

    res.render('formula-list', { 
     formulas: docs, 
     title: 'Your Formulas', 
     description: `List of saved user formulas from the formula generator`, 
     ID: 'formula-list', 
     keywords: 'formula generator, health kismet, nutraceutical formula builder' 
    }); 
    }); 
}); 
1

Sie benötigen db init-Code bis bewegen (vor Ihren Routen Definition) und füge eine Middleware, die den mongodb-Treiber in das req-Objekt einschließt. Etwas wie:

mongo.connect('mongodb://localhost:27017/formulas', function(err, db){ 
    app.use(function(req, res, next){ 
     req.db = db; 
     next(); 
    }); 
}); 

app.use(root); ... 
+0

Dies könnte zu einigen Problemen führen, da Sie weiterhin Handler mounten und die App hochfahren, während Sie auf die Beendigung der Verbindung warten. Die 'app.use'-Reihenfolge ist wichtig, und dies führt sehr wahrscheinlich dazu, dass 'req.db' auf Routen nichtdeterministisch verfügbar ist, abhängig davon, wie lange die Verbindung dauert. Außerdem glaube ich, dass dies zu einer Verbindung für alle Anfragen führen wird, was sich ebenfalls auf die Leistung auswirkt. – Paul

3

OK, also bevor die erste Route zu erklären, der die Verbindung benötigt, werden Sie möchten Ihre Middleware verdrahten, um die DB-Verbindung auf die Anforderung zuweisen. Wahrscheinlich ist es eine gute Idee, die Ressource erneut zu veröffentlichen, nachdem die Antwort gesendet wurde, es sei denn, Sie verwenden das Verbindungspooling.

app.use((req, res, next) => { 
    mongo.connect('mongodb://localhost:27017/formulas', (e, db) => { 
    if (e) return next(e); 
    req.db = db; 
    next(); 
    }); 

    // cleanup 
    req.on('end',() => { req.db.close(); }); 
}); 

Hoffe, dass hilft.

+0

Ich ging voran und machte Ihre Änderungen und bekomme immer noch den gleichen Fehler. Ich habe meine 'app.js' Datei in der obigen Frage aktualisiert, um zu reflektieren, was ich gerade habe. Irgendeine Idee, was könnte schief gehen? –

+1

Was erwarten Sie von db.formulas? Ich sehe das nirgendwo. Der Mongo-Client und der Mongo-Treiber verwenden nicht die gleiche Syntax, ich denke, was Sie versuchen, ist etwas wie req.db.collection ('Formeln'). ​​Find(). Wenn "req.db" nicht definiert ist, dann stimmt etwas anderes nicht. Was passiert, wenn Sie console.log (req.db) in der Mitte verwenden, die Sie zuerst verwenden (die mit dem Aufruf mongo.connect)? – Paul

+0

'Formeln' ist eine Mongodb-Sammlung, die bereits mit ein paar Dokumenten bevölkert ist. Ich begann Mönch für dieses Projekt zu verwenden, wechselte aber zu MongoDB, um die Datenbank besser zu lernen, daher die Probleme mit dem Treiber. Ich habe die obige Frage aktualisiert, um den Inhalt von 'console.log (req.db)' zu enthalten. –

3

Versuchen Sie es so zu verwenden

db.collection('collectionName').find({}).toArray(function(e, docs){ 
    res.render('formula-list', { 
    formulas: docs, 
    title: 'Your Formulas', 
    description: `List of saved user formulas from the formula generator`, 
    ID: 'formula-list', 
    keywords: 'formula generator, health kismet, nutraceutical formula 
    builder' 
    }); 

});

Hoffnung Es hilft.

1

db.formulas existiert nicht, dies ist eine kurze Hand von der Mongo REPL.

In Knoten.js müssen Sie zuerst die Sammlung erhalten mit

db.collection('name')

Das bedeutet, statt db.formulas.find tun Sie tun können:

db.collection('formulas').find({}, {}, function(e, docs){})

Sie könnten alternativ tun:

db.formulas = db.collection('formulas'); db.another = db.collection('another');

Es ist jedoch immer am besten, keine Werbung zu machen d in "magic code"