【问题标题】:Best way to connect to MongoDB using Node.js [duplicate]使用 Node.js 连接到 MongoDB 的最佳方式 [重复]
【发布时间】:2016-11-23 22:40:40
【问题描述】:

我已经阅读了一些关于如何将 Mongo 与 Node 一起使用的指南,它们似乎都以不同的方式连接到数据库。一种特别适合我的方法是:

MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
  if(err) { return console.dir(err); }

  db.createCollection('users', function(err, collection) {});

  //Do all server/database operations in here

});

但是,这对我来说似乎效率低下/奇怪,每次有 app.get() 时,我都必须重新连接到数据库,例如创建新用户或检索信息。

另一种似乎更适合我的方式是

var mongoose = require("mongoose")
var db = mongoose.connect("localhost:27107/users");

db.createCollection('users', function(err, collection) {});

我已经看到几个网站在这些方面做了一些事情,但我个人无法让上述内容起作用。我不断收到错误TypeError: db.createCollection is not a function 服务器端。所以,我的问题是为什么上面的代码不起作用,如果第一个代码是一个很好的选择,以及是否有其他方法可以做到这一点。

【问题讨论】:

    标签: node.js mongodb


    【解决方案1】:

    您可以使用全局变量来保持连接(例如db),例如:

    var db = null // global variable to hold the connection
    
    MongoClient.connect('mongodb://localhost:27017/', function(err, client) {
        if(err) { console.error(err) }
        db = client.db('test') // once connected, assign the connection to the global variable
    })
    
    app.get('/', function(req, res) {
        db.collection('test').find({}).toArray(function(err, docs) {
            if(err) { console.error(err) }
            res.send(JSON.stringify(docs))
        })
    })
    

    或者,如果您愿意,也可以使用 MongoClient 返回的 Promise 对象,如果它在没有回调参数的情况下调用:

    var conn = MongoClient.connect('mongodb://localhost:27017/') // returns a Promise
    
    app.get('/', function(req, res) {
        conn.then(client=> client.db('test').collection('test').find({}).toArray(function(err, docs) {
            if(err) { console.error(err) }
            res.send(JSON.stringify(docs))
        }))
    })
    

    请注意,我在第二个示例中使用了ES6 fat arrow function definition

    您绝对正确,您不应该每次都致电MongoClient。使用全局变量或 Promises 可以让 MongoDB node.js 驱动创建一个连接池,这至少实现了两个好处:

    • 连接在池中重复使用,因此在应用程序的生命周期内没有多个昂贵的设置/拆卸过程。您只需连接一次,然后让司机为您处理剩下的事情。
    • 您可以通过限制连接池的大小来控制应用程序与数据库的连接量。

    编辑 2018-08-24:node.js 驱动程序 3.0 及更高版本中的 MongoClient.connect() 方法返回 client object 而不是数据库对象。修改了上面的示例以使其与最新的 node.js 驱动程序版本保持同步。

    【讨论】:

    • 我得到通用处理程序 TypeError: db.collection is not a function error.When I used the first example of ur's.我该如何解决这个问题?
    • 请查看更新后的答案。
    • 您能否展示如何正确创建池以供重复使用,以及如果其中一个发生错误时如何更新它们?
    【解决方案2】:

    我写了一篇关于如何在 express 中重用 mongodb 连接的教程。你可以看到here。基本上,它是一个简单的模块,你可以像这样与 expressjs 一起使用:

    var connection = require('./dbconnection');  
    // url and optional config.
    app.use(connection(app, 'mongourl', {});
    

    这是连接的代码:

    module.exports = function(app, uri, opts) {  
        if (typeof uri !== 'string') {
            throw new TypeError('Error: Unexpected mongodb connection url');
        }
    
        opts = opts || {};
        var property = opts.property || 'db';
    
        var connection;
        return function expressMongoDb(req, res, next) {
            if (!connection) {
                connection = MongoClient.connect(uri, opts);
            }
    
            connection
                .then(function (db) {
                    req[property] = db;
                    app.set('mongodb', db);
                    next();
                })
                .catch(function (err) {
                    connection = undefined;
                    next(err);
                });
        };
    };
    

    【讨论】:

      【解决方案3】:

      你可以这样使用它:

      那是 server.js 文件:

      import path from 'path'
      import express from 'express'
      import bodyParser from 'body-parser'
      import morgan from 'morgan'
      import db from './server/database'
      import routes from './server/routes'
      
      import webpack from 'webpack'
      import webpackDevMiddleware from 'webpack-dev-middleware'
      import webpackHotMiddleware from 'webpack-hot-middleware'
      import webpackConfig from './config/webpack'
      const app = express()
      const port = process.env.PORT || process.env.NODE_PORT
      const compiler = webpack(webpackConfig)
      
      db(λ => {
        app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: webpackConfig.output.publicPath }))
        app.use(webpackHotMiddleware(compiler))
        app.use(morgan('dev'))
        app.use(bodyParser.json({ limit: '20mb' }))
        app.use(bodyParser.urlencoded({ limit: '20mb', extended: false }))
        app.use('/static', express.static('static'));
        //app.use('/api', jwt)
        app.use('/api', routes())
      
        app.set('json spaces', 2)
      
        app.get('*', function(request, response) {
          response.sendFile(path.resolve(__dirname, 'index.html'))
        })
      
        app.listen(port, (error) => {
          if (error) {
            console.error(error)
            throw error
          } else {
            console.info(`==> ?  Listening on port ${port}. Open up http://localhost:${port}/ in your browser.`)
          }
        })
      })
      

      服务器/数据库.js

      import mongoose from 'mongoose'
      
      export default callback => {
        const { MONGO_URL, MONGO_PORT, MONGO_DB } = process.env
      
        mongoose.connect(`mongodb://${MONGO_URL}:${MONGO_PORT}/${MONGO_DB}`, error => {
          if (error) {
            console.error('Please make sure your MongoDB configuration is correct and that service is running')
            throw error
          }
        })
      
        callback()
      }
      

      然后你必须定义你的猫鼬模型,例如:

      import mongoose, { Schema } from 'mongoose'
      
      const ideaSchema = new Schema({
        title: {
          type: String,
          required: true
        },
        slug: {
          type: String,
          required: true,
          unique: true
        },
        description: {
          type: String,
          required: true
        }
      })
      
      export default mongoose.model('Idea', ideaSchema)
      

      只需以这种方式使用控制器:

      import HttpStatus from 'http-status-codes'
      import mongoose from 'mongoose'
      import sanitize from 'sanitize-html'
      import slug from 'slug'
      import Idea from '../models/idea'
      
      const findAllIdeas = (req, res) => {
        Idea.find()
          .select('user title slug createdAt updatedAt')
          .populate({
            path: 'user',
            select: 'firstName lastName'
          })
          .then(data => res.status(HttpStatus.OK).json(data))
          .catch(error => res.status(HttpStatus.BAD_REQUEST).json(error))
      }
      
      export default { findAllIdeas, findIdeaBySlug, createIdea, addComment }
      

      您不必为每个 get 请求连接到 mongoDB。

      所以你的路线看起来像这样。很简单:

      import { Router } from 'express'
      import controller from '../controllers/idea'
      
      const router = Router()
      
      router.route('/')
        .get(controller.findAllIdeas)
        .post(controller.createIdea)
      
      router.route('/:slug')
        .get(controller.findIdeaBySlug)
      
      router.route('/comment')
        .post(controller.addComment)
      
      export default router
      

      【讨论】:

      • 非常有趣,感谢您的帮助。我个人对使用任何我不理解的代码(在这个程度上)犹豫不决,尽管我会解决这个问题,
      • 我认为这比 OP 要求的要多...
      【解决方案4】:

      我的首选代码如下:

      mongoose.connect(YOUR_URL ,function(err) {
        if (err) {
          console.log(err);
        }else{
          console.log("Connected to DB"); 
        }
      });
      

      还可以尝试仅连接到 localhost:27107,这可能是您的问题。

      【讨论】:

      • 是的,这行得通,但正如我所问的,它是否足够高效地用于每个app.get()?或者那是无关紧要的?
      • 是的,只要把这段代码放在server.js中,在其他要查询MongoDB的文件中,只需var mongoose = require('mongoose');,然后var Model= require('./models/MODEL');,如果在server.js中,它只会启动时连接一次。
      猜你喜欢
      • 1970-01-01
      • 2016-11-30
      • 2017-04-22
      • 2022-06-28
      • 1970-01-01
      • 2023-03-14
      • 2018-05-15
      • 2013-09-13
      • 1970-01-01
      相关资源
      最近更新 更多