Зачем подключаться и закрывать клиента mongodb после каждого запроса? [Дубликат]

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

58
задан tereško 8 July 2014 в 07:39
поделиться

6 ответов

Вот как я это делаю с современным синтаксисом, основанным на примере go-oleg.

Я добавил несколько комментариев в код.

./ db / mongodb.js

 const MongoClient = require('mongodb').MongoClient
 const uri = 'mongodb://user:password@localhost:27017/dbName'
 let _db

 const connectDB = async (callback) => {
     try {
         MongoClient.connect(uri, (err, db) => {
             _db = db
             return callback(err)
         })
     } catch (e) {
         throw e
     }
 }

 const getDB = () => _db

 const disconnectDB = () => _db.close()

 module.exports = { connectDB, getDB, disconnectDB }
< blockquote>

./ index.js

 // Load MongoDB utils
 const MongoDB = require('./db/mongodb')
 // Load queries & mutations
 const Users = require('./users')

 // Improve debugging
 process.on('unhandledRejection', (reason, p) => {
     console.log('Unhandled Rejection at:', p, 'reason:', reason)
 })

 const seedUser = {
     name: 'Bob Alice',
     email: 'test@dev.null',
     bonusSetting: true
 }

 // Connect to MongoDB and put server instantiation code inside
 // because we start the connection first
 MongoDB.connectDB(async (err) => {
     if (err) throw err
     // Load db & collections
     const db = MongoDB.getDB()
     const users = db.collection('users')

     try {
         // Run some sample operations
         // and pass users collection into models
         const newUser = await Users.createUser(users, seedUser)
         const listUsers = await Users.getUsers(users)
         const findUser = await Users.findUserById(users, newUser._id)

         console.log('CREATE USER')
         console.log(newUser)
         console.log('GET ALL USERS')
         console.log(listUsers)
         console.log('FIND USER')
         console.log(findUser)
     } catch (e) {
         throw e
     }

     const desired = true
     if (desired) {
         // Use disconnectDB for clean driver disconnect
         MongoDB.disconnectDB()
         process.exit(0)
     }
     // Server code anywhere above here inside connectDB()
 })

./ users / index.js

 const ObjectID = require('mongodb').ObjectID

 // Notice how the users collection is passed into the models
 const createUser = async (users, user) => {
     try {
         const results = await users.insertOne(user)
         return results.ops[0]
     } catch (e) {
         throw e
     }
 }

 const getUsers = async (users) => {
     try {
         const results = await users.find().toArray()
         return results
     } catch (e) {
         throw e
     }
 }

 const findUserById = async (users, id) => {
     try {
         if (!ObjectID.isValid(id)) throw 'Invalid MongoDB ID.'
         const results = await users.findOne(ObjectID(id))
         return results
     } catch (e) {
         throw e
     }
 }

 // Export garbage as methods on the Users object
 module.exports = { createUser, getUsers, findUserById }
4
ответ дан agm1984 18 August 2018 в 19:45
поделиться
  • 1
    нужен ли улов try в вашем первом фрагменте? функция подключения является асинхронной. Ошибка уже улавливается с помощью обратного вызова стиля узла. – shanks 16 May 2018 в 21:44
  • 2
    Это очень замечательный вопрос, который я люблю. Я не уверен, не изучая его ближе в среде обитания, где вы размещаете код. Будет ограниченное количество путей, которые могут потребоваться при выполнении кода. Я добавил его в основном, чтобы показать, что вы можете поставить пользовательский обработчик и потому, что я по умолчанию включаю try / catch в async-функции. Это просто точка крючка. Хороший вопрос. Я обновлю, если вы найдете дополнительную заметку. – agm1984 17 May 2018 в 22:08

Вы можете создать модуль mongoUtil.js, который имеет функции как для подключения к mongo, так и для возврата экземпляра mongo db:

var MongoClient = require( 'mongodb' ).MongoClient;

var _db;

module.exports = {

  connectToServer: function( callback ) {
    MongoClient.connect( "mongodb://localhost:27017/marankings", function( err, db ) {
      _db = db;
      return callback( err );
    } );
  },

  getDb: function() {
    return _db;
  }
};

Чтобы использовать его, вы сделаете это в своем app.js:

var mongoUtil = require( 'mongoUtil' );

mongoUtil.connectToServer( function( err ) {
  // start the rest of your app here
} );

И тогда, когда вам нужен доступ к mongo где-нибудь, вы можете сделать это:

var mongoUtil = require( 'mongoUtil' );
var db = mongoUtil.getDb();

db.collection( 'users' ).find();

Причина этого в том, что в узле, когда модули require 'd, они только загружаются / получаются один раз, так что вы только когда-нибудь закончите с одним экземпляром _db, а mongoUtil.getDb() всегда вернет тот же самый экземпляр.

Примечание, код не проверен.

86
ответ дан go-oleg 18 August 2018 в 19:45
поделиться
  • 1
    Отличный пример! Однако у меня есть вопрос. Как это будет работать при запуске вашего приложения с несколькими кластерами? Разве это запустит другой экземпляр подключения или просто использует существующее соединение из источника? – Farhan Ahmad 9 February 2015 в 03:59
  • 2
    Работает как шарм, спасибо! – Arpit 23 December 2016 в 17:26
  • 3
    Как вы справитесь с тем случаем, когда соединение монго будет умирать между ними? Все вызовы getDb () не будут выполняться в этом сценарии до тех пор, пока приложение узла не будет перезапущено. – Ayan 22 August 2017 в 12:02
  • 4
    Я пробовал этот код, но я получил null, когда делаю mongoUtil.getDb (), я не знаю, почему это так. – Keming 17 January 2018 в 20:44
  • 5
    @KemingZeng - вам нужно убедиться, что все модули, которые используют mongoUtil, импортируются в app.js в функции обратного вызова из connectToServer. Если вы require их в app.js до _db установлены, то вы получите неопределенные ошибки в других модулях. – Mike 17 February 2018 в 22:40
  • 6
    – Julian Veerkamp 23 August 2018 в 12:01

go-oleg в принципе прав, но в эти дни вы (вероятно) не хотите использовать «mongodb» самостоятельно, скорее используйте некоторую фреймворк, которая сделает для вас много «грязной работы».

Например, мангуст является одним из самых распространенных. Это то, что мы имеем в нашем исходном файле server.js:

const mongoose = require('mongoose');
const options = {server: {socketOptions: {keepAlive: 1}}};
mongoose.connect(config.db, options);

Это все, что необходимо для его настройки. Теперь используйте это в любом месте вашего кода

const mongoose = require('mongoose');

И вы получите тот экземпляр, который вы установили с помощью mongoose.connect

4
ответ дан libik 18 August 2018 в 19:45
поделиться
  • 1
    Мангуста - это ОРМ. Прочитайте этот , чтобы узнать о возможных ловушках для того же самого. Без сомнения, ORM великолепны при использовании для процесса развития и обучения, но не для производства. Просто помните об этом – Saras Arya 13 April 2017 в 14:16
  • 2
    Mongoose также требует схем. Я использую пакет MongoDB как часть сохранения многоугольника с Neo4j, поэтому неплохо определить свойства документа по мере необходимости. – agm1984 24 July 2017 в 06:10

Если вы используете Express, то вы можете использовать модуль express-mongo-db , который позволяет вам получить соединение db в объекте запроса.

Установить

npm install --save express-mongo-db

server.js

var app = require('express')();

var expressMongoDb = require('express-mongo-db');
app.use(expressMongoDb('mongodb://localhost/test'));

routes / users.js

app.get('/', function (req, res, next) {
    req.db // => Db object
});
8
ответ дан Mukesh Chapagain 18 August 2018 в 19:45
поделиться

Проверенное решение на основе принятого ответа:

mongodbutil.js:

var MongoClient = require( 'mongodb' ).MongoClient;
var _db;
module.exports = {
  connectToServer: function( callback ) {
    MongoClient.connect( "<connection string>", function( err, client ) {
      _db = client.db("<collection name>");
      return callback( err );
    } );
  },
  getDb: function() {
    return _db;
  }
};

app.js :

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

var mongodbutil = require( './mongodbutil' );
mongodbutil.connectToServer( function( err ) {
  //app goes online once this callback occurs
  var indexRouter = require('./routes/index');
  var usersRouter = require('./routes/users');
  var companiesRouter = require('./routes/companies');
  var activitiesRouter = require('./routes/activities');
  var registerRouter = require('./routes/register');  
  app.use('/', indexRouter);
  app.use('/users', usersRouter);
  app.use('/companies', companiesRouter);
  app.use('/activities', activitiesRouter);
  app.use('/register', registerRouter);  
  // catch 404 and forward to error handler
  app.use(function(req, res, next) {
    next(createError(404));
  });
  // error handler
  app.use(function(err, req, res, next) {
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};
    res.status(err.status || 500);
    res.render('error');
  });
  //end of calback
});

module.exports = app;

activities.js - маршрут:

var express = require('express');
var router = express.Router();
var mongodbutil = require( '../mongodbutil' );
var db = mongodbutil.getDb();

router.get('/', (req, res, next) => {  
    db.collection('activities').find().toArray((err, results) => {
        if (err) return console.log(err)
            res.render('activities', {activities: results, title: "Activities"})
    });
});

router.post('/', (req, res) => {
  db.collection('activities').save(req.body, (err, result) => {
    if (err) return console.log(err)
    res.redirect('/activities')
  })
});

module.exports = router;

0
ответ дан steve 18 August 2018 в 19:45
поделиться
1
ответ дан Henry Bothin 30 October 2018 в 08:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: