joec
joec

Reputation: 3543

Connecting to MongoDB using Mongoose in multiple files

I'm new to using mongoose and MongoDB. I'm developing a React-Redux app for saving Todo lists. I'm using webpack to bundle everything.

What is the best way to connect to my MongoDB in multiple files? For example, when my initial app.jsx runs, and then in my reducers.jsx file to save to the database...

I know that mongoose maintains a persistent connection, but whenever I try to use

var mongoose = require('mongoose');

I get this webpack error

WARNING in ./~/mongoose/lib/drivers/index.js Critical dependencies: 8:11-74 the request of a dependency is an expression @ ./~/mongoose/lib/drivers/index.js 8:11-74

When i create a separate test app, I can successfully write to MongoDB using

mongoose.connect() and the .save() methods, when everything is kept in one file.

Thanks

App.jsx

var React = require ('react');
var ReactDOM = require ('react-dom');
var {Route, Router, IndexRoute, hashHistory} = require ('react-router');

var {Provider} = require('react-redux');

var TodoApp = require('TodoApp');

var actions = require('actions');
var store = require('configureStore').configure();
var TodoAPI = require('TodoAPI');


// Connect to MongoDB using mongoose
var url = 'mongodb://joe:[email protected]:47487/reacttodo';
var mongoose =require('mongoose');
mongoose.connect(url);


store.subscribe(()=>{
  var state = store.getState();
  console.log('new state',state);
  TodoAPI.setTodos(state.todos);
});

var initialTodos = TodoAPI.getTodos();
store.dispatch(actions.addTodos(initialTodos));

// load foundation
$(document).foundation();

//app css
require('style!css!sass!AppStyles');

ReactDOM.render(
  <Provider store={store}>
    <TodoApp/>
  </Provider>,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Upvotes: 2

Views: 6661

Answers (1)

AndreaM16
AndreaM16

Reputation: 3985

You need to require Mongoose and open a new connection to it in your server.js so you can access it through different modules.

Suppose you are using both express and body-parser

server.js:

. . .
var mongoose   = require('mongoose');
var port       = process.env.PORT || 3000;
var express    = require('express');
var bodyParser = require('body-parser');
. . .
var app             = express();
mongoose.connect("mongodb://localhost/MyApp");
. . .
app.use(bodyParser.json());
. . .
require('./app/routes.js')(app);
app.listen(port);
console.log('App listening on port ' + port);

Then, you can access it easily. Let's suppose you want to set-up a mongoose schema.

mySchema.js:

var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

var user = new Schema({
          name: {type: String, required : true}
});

module.exports = mongoose.model('user', user);

Or you just want to retrieve all user or save a new user to the user collection, supposing you are passing it an object req which has some properties like name:

user.factory.js

require('mongoose');
var User = require('mySchema.js');

exports.getUsers = getUsers;
exports.postUser = postUser;

function getUsers() {
  return new Promise( function (resolve, reject) {
    var query = User.find({});
    query.exec(function(err, users) {
        if (err){
            return reject({err : 'Error while fetching users'});
        }
        // If no errors are found, it responds with a JSON of all users
        return resolve(users);
     });
  });
}



function postUser(req) {
    return new Promise( function (resolve, reject) {
    // Creates a new User based on the Mongoose schema and the post body
      var newUser = new User(req.body);
      // New User is saved in the db.
      newUser.save(function(err) {
          console.log('err',err);
          if (err){
              return reject({err : 'Error while saving new user'});
          }
          // If no errors are found, it responds with a JSON of the new users
          return resolve(req.body);
      });
    });
}

Also, suppose you want to set-up a route to intercept http requests. For instance, a request to save a new user.

routes.js:

var UserFactory = require('./factories/user.factory.js');

// Opens App Routes
module.exports = function(app) {

   /** Getting all the users **/
   app.get('/users', function(req, res) {
     UserFactory.getUsers().then( function (users) {
        res.json(users);
     }, function (error) {
        res.json(error);
     });
   });

   /** Posting a new geometry **/
   app.post('/users', function(req, res) {
     UserFactory.postUsers(req).then( function (user) {
        return res.json(user);
     }, function (error) {
        res.json(error);
     });
   });

}

And, on the front-end, the user inserts a user name in a form, then clicks on submit button and you call a createNewUser function:

. . .
var createNewUser = function(userName){

   var user = {
                  name : userName //Goofy
   };

   console.log(user.name); //Goofy

   postNewUser(user).then( function( response, err){
     if(err){
       console.log('Error while saving new user');
     } else {
       console.log('User '+response+' successfully saved');
     }
   });

}

function postNewUser(user){
  return new Promise(function (resolve, reject) {
     // Saves user data to the db
     $http.post('/users', user)
          .success(function(res) {
            if(res.error){
               return reject(res.error);
            }
               return resolve(res);
     });
   });
  }

You can also set mongoose globally in your server.js so you don't need to require it in your modules

var mongoose = require('mongoose');
. . .
global.mongoose = mongoose;

Hope I've been helpful.

Upvotes: 6

Related Questions