How this save method on mongoose works without saying which database? - javascript

So first, I have a workspace folder called "Projects"
In this folder, I have 2 folders:
Models:
1) Something-model =>
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Something-Schema = new Schema({
name: String,
weight: Number,
length: Number
});
const Something-model = mongoose.model(
"SomeModel",
Something-Schema
);
module.exports = Something-model;
Job: A model for a record.
Database:
1) Connection.js =>
const mongoose = require("mongoose");
//connect to mongoDB
mongoose.connect(
"mongodb://localhost/Database",
{ useNewUrlParser: true }
);
mongoose.connection
.once("open", () => {
console.log("Connection has been made!");
})
.on("error", err => {
console.log("Connection hasn't been made. Got this: " + err);
});
Job: It connects to the database.
2) Saving-test.js =>
let assert = require("assert");
let someModel = require("../Models/StevenChars");
// Data Saving Test
describe("Data-Saving", function() {
it("Saving a data to database", function() {
let Record-One = new someModel({
name: "Jack",
weight: 55,
height: 150
});
Record-One.save().then(function() {
assert(Record-One.isNew === false);
});
});
});
Job: To save a record to the database.
Now the problem is that how save() is supposed to save anything if it doesn't know the location of the database it's going to save to(Which is in Connection.js btw)?
I did it in mocha and it says that the test has passed but I'm still confused how this works. I only followed steps of Net Ninja tutorial but he didn't explain how save() actually works.
So how this works? Excuse me guys if this is a stupid question, I'm a very beginner to servers and databases and I searched about how save works and I didn't get the answer I did. I would really be thankful if someone tried to explain this to me.

From what it seems you are trying to do the goal is to create a mocha unit test which would write to mongodb via mongoose as a provider.
Ok so that is the task at hand. To do that you need to be familiar with few things:
Mocha and how tests are written. Why do you need "before" and "after" and their main purpose.
Mongoose Models and how they work in terms of CRUD
MongoDB so you can actually connect and see if you got the expected results after/during your tests
With that being said here is an example of such a test:
describe('Database Tests', function() {
//Before starting the test, create a database connection
//Once a connection is established invoke done()
before(function (done) {
mongoose.connect('mongodb://localhost/testDatabase');
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error'));
db.once('open', function() {
console.log('We are connected to test database!');
done();
});
});
describe('Test Database', function() {
//Save object with 'name' value of 'Mike"
it('New name saved to test database', function(done) {
var testName = Name({
name: 'Mike'
});
testName.save(done);
});
});
//After all tests are finished drop database and close connection
after(function(done){
mongoose.connection.db.dropDatabase(function(){
mongoose.connection.close(done);
});
});
});
You can see more of this example here or just search for mocha mongoose testing.

I was wrong. It's not about save method, I just had to run the connection together with all the files by using Mocha
That's all. The post can be closed and solved now.

Related

Unresolved function or method connect() mongoose

I am learning Mongoose from JavaScript Everywhere book, and this is the code I had to write:
const mongoose = require('mongoose');
const mongoose = require('mongoose');
module.exports = {
connect: DB_HOST => {
mongoose.connect(DB_HOST);
mongoose.connection.on('error', err => {
console.error(err);
console.log('MongoDB connection error. Please make sure MongoDB is running.');
process.exit();
});
},
close: () => {
mongoose.connection.close();
}
}
when i hover over connect and connection, it shows Unresolved function or method connect() and Unresolved variable connection accordingly. My guess is that the book about an older version of mongoose, and in the newest version it is simply removed. What is the new function and variable for it?
Even though it's been some time.
replace your mongoose require with this:
const mongoose = require('mongoose').default;
should solve it for WebStorm
Still, I'd recommand using mongodb instead
I'm also learning Mongoose and have the same situation as you; here's how I fixed my error – you can use it as a reference to fix your code:
const {connect: connect1} = require('mongoose')
async function connect() {
try {
await connect1('DB_HOST')
console.log('\n Connected successfully')
} catch (err) {
console.log('\n Disconnect')
}
}
module.exports = { connect }

mongoose is not creating db using mongoose.connect

I'm trying to create new database using mongoose.connect('mongodb://localhost:27017/imagesDB'); But is not creating. And please don't answer me saying that I need to add entries to it. I did it. Here's my full code.
const express = require("express");
const mongoose = require('mongoose');
const app = express();
mongoose.connect('mongodb://localhost:27017/imagesDB').then(() => {
console.log("Connected to Database");
}).catch((err) => {
console.log("Not Connected to Database ERROR! ", err);
});
const imageSchema = new mongoose.Schema ({
name: String,
category: String,
author: String,
tag: String,
imageURL: String
});
const Image = mongoose.model("Image", imageSchema);
const image = new Image({
name: "Cat",
category: "Animal",
author:"Cat",
tag: "Animals",
imageURL: "https://cdn-media-2.freecodecamp.org/w1280/5f9c9a5d740569d1a4ca2531.jpg"
});
image.save();
app.get("/", function(req, res){
res.send("Everything is running properly!");
});
app.listen(3000, function(){
console.log("Server succesfully started on port 3000!");
});
Can you guys please test it for yourself? Does this creates a new database called imagesDB???
For me no, It is not working. I opened new tab in terminal and commanded mongo so it opened mongo client where i typed show dbs but it is not showing except these three admin, config and local.
I also wanna make it clear that mongo service is running, I did it by commanding mongod --ipv6 in terminal.
The problem is solved by changing localhost to 127.0.0.1 .
Here's how it looks
mongoose.connect('mongodb://127.0.0.1:27017/imagesDB').then(() => {
console.log("Connected to Database");
}).catch((err) => {
console.log("Not Connected to Database ERROR! ", err);
});
Are you using Mongoose Compass or Atlas?
Secondly, try doing it on VSCode terminal it will work then
You have to created your database named "imagesDB" in MongoDB Compass, or other GUI tool.

Node.js Database Module with Sequelize

To make my code more readable, I'm trying to move all database related code into a single file. and use Sequelize as ORM. I would like that this file, when included provide a ready to use Database. Tables schemas are also managed by Sequelize which is why I use the sync() method to create the tables on the first run. Unfortunately, when I run the application for the first time, I get an error that the table doesn't exist when using this code:
File: test.js
const database = require('./dbInit');
(async () => {
await database.testTable.max('id').then((maxId) => {
console.log(maxId);
});
})();
File: dbInit.js
const Sequelize = require('sequelize');
const sequelize = new Sequelize('mysql://root:root#localhost:3306/test');
const testTable = sequelize.import('testTable');
const database = {
sequelize: sequelize,
testTable: testTable,
};
sequelize
.authenticate()
.then(() => {
console.log('Connection to the database has been established successfully.');
})
.catch(error => {
console.error(error);
});
sequelize.sync();
module.exports = database;
File: testTable.js
const Sequelize = require('sequelize');
module.exports = (sequelize, DataTypes) => {
return sequelize.define('testTable',
{
id: {
type: Sequelize.BIGINT(19).UNSIGNED,
primaryKey: true,
autoIncrement: false,
}
}
);
};
When I run the code as is, without tables created, I can see from the logs that the query is run before the connection to the database is available:
> node .\test.js
Executing (default): SELECT 1+1 AS result
Executing (default): SELECT max(`id`) AS `max` FROM `testTables` AS `testTable`;
Connection to the database has been established successfully.
(node:1572) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: Table 'test.testtables' doesn't exist
I have found a way to make it work by adding this like, just before the call to the DB (in test.js before the max('id') call):
await database.sequelize.sync();
Is there any other way to have the dbInit module completely independent and not having to add this sync() call inside all other files which will require database connectivity?
I've looked for sync module loading but it doesn't seem an option yet.
Because of async behavior all of ops that You want to do:
Connect
Sync
Do DB operations
You've to make it following way:
put model files to: db folder as: db/schemas/User.js
and make module file for db: db/index.js
const Sequelize = require('sequelize');
const sequelize = new Sequelize('mysql://root:root#localhost:3306/test');
const connect = async () => {
try {
await sequelize.authenticate();
await sequelize.sync();
console.log('Connection to the database has been established successfully.');
}
catch (error) {
console.error(error.message);
process.exit(-1);
}
});
const model = name => database.models[name];
const User = sequelize.import('./schemas/User');
const database = {
sequelize: sequelize,
models: {User},
connect,
model
};
module.exports = database;
and in test.js:
const db = require('./db');
(async () => {
await db.connect();
const User = db.model('User');
const id = await User.max('id');
console.log(id);
})();
P.S. forget about examples that used in web apps when developer does not care when db will connect and when express app will listen on port.
Your question is different - You want to do db query immediately, so You've to make sure connection and sync established successfully.
You can follow up my github repo Sequelize-DemoApp. It's a fully working full stack application made especially to demonstrate and understand Sequelize.js and it's integration with nodejs

Searching for best practice to use one mongodb connection in multiple javascript-files

At the moment, I develop a node.js REST webservice with express. I used MongoDB + Mongoose to establish a database.
Now, I have the problem, that I can only use the db connection in the file where I established the connection. I found a solution to use the connection also in other files by "module.exports" the _db variable. But I don't know, if this is the best practise. Here is my code:
databaseManager.js
// Establish a connection to the database.
mongoose.Promise = global.Promise
mongoose.connect('mongodb://'+cfg.db.ip+':'+cfg.db.port+'/'+cfg.db.name)
var _db = mongoose.connection
_db.on('error', console.error.bind(console, 'DB connection error'))
_db.once('open', function()
{
console.log("DatabaseM: Connected to the database")
})
[...]
module.exports =
{
db : _db,
}
otherFile.js
var database = require('./databaseManagement')
[...]
database.db.collection('users').findOne({ name: "ashton"}, function(err, user)
{
if (err) return callback(consts.ERROR_DB, null)
if (!user) return callback(consts.WARN_DB_NO_CLIENT)
callback(null, user)
})
It works great. But there may be a risk that I do not see?
Thanks a lot :-)
In your app.js file :
var url="mongdb:\\localhost:27017\dbname";
mongoose.connect(url); //it open default connection for mongodb and is handled by mongoose
Now perform all your task whatever you want :
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection open to ' + dbURI);
});
Bring all your database model in app.js file like as such:
var model1 = require('./models/model1');
model1.js
var mongoose = require('mongoose');
var data = new mongoose.Schema({
name:{type:String, required:true}
});
module.exports = mongoose.model('collectionName', data);
Now, when all your tasks are over. Simply close default connection like this :
mongoose.connection.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
});
If any error occurs in connection handle it like this :
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
If node service exits then close connection usig this code
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});

Mongoose and multiple database in single node.js project

I'm doing a Node.js project that contains sub projects. One sub project will have one Mongodb database and Mongoose will be use for wrapping and querying db. But the problem is
Mongoose doesn't allow to use multiple databases in single mongoose instance as the models are build on one connection.
To use multiple mongoose instances, Node.js doesn't allow multiple module instances as it has caching system in require(). I know disable module caching in Node.js but I think it is not the good solution as it is only need for mongoose.
I've tried to use createConnection() and openSet() in mongoose, but it was not the solution.
I've tried to deep copy the mongoose instance (http://blog.imaginea.com/deep-copy-in-javascript/) to pass new mongoose instances to the sub project, but it throwing RangeError: Maximum call stack size exceeded.
I want to know is there anyways to use multiple database with mongoose or any workaround for this problem? Because I think mongoose is quite easy and fast. Or any other modules as recommendations?
According to the fine manual, createConnection() can be used to connect to multiple databases.
However, you need to create separate models for each connection/database:
var conn = mongoose.createConnection('mongodb://localhost/testA');
var conn2 = mongoose.createConnection('mongodb://localhost/testB');
// stored in 'testA' database
var ModelA = conn.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testA database' }
}));
// stored in 'testB' database
var ModelB = conn2.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testB database' }
}));
I'm pretty sure that you can share the schema between them, but you have to check to make sure.
Pretty late but this might help someone. The current answers assumes you are using the same file for your connections and models.
In real life, there is a high chance that you are splitting your models into different files. You can use something like this in your main file:
mongoose.connect('mongodb://localhost/default');
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('connected');
});
which is just how it is described in the docs. And then in your model files, do something like the following:
import mongoose, { Schema } from 'mongoose';
const userInfoSchema = new Schema({
createdAt: {
type: Date,
required: true,
default: new Date(),
},
// ...other fields
});
const myDB = mongoose.connection.useDb('myDB');
const UserInfo = myDB.model('userInfo', userInfoSchema);
export default UserInfo;
Where myDB is your database name.
One thing you can do is, you might have subfolders for each projects. So, install mongoose in that subfolders and require() mongoose from own folders in each sub applications. Not from the project root or from global. So one sub project, one mongoose installation and one mongoose instance.
-app_root/
--foo_app/
---db_access.js
---foo_db_connect.js
---node_modules/
----mongoose/
--bar_app/
---db_access.js
---bar_db_connect.js
---node_modules/
----mongoose/
In foo_db_connect.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/foo_db');
module.exports = exports = mongoose;
In bar_db_connect.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bar_db');
module.exports = exports = mongoose;
In db_access.js files
var mongoose = require("./foo_db_connect.js"); // bar_db_connect.js for bar app
Now, you can access multiple databases with mongoose.
As an alternative approach, Mongoose does export a constructor for a new instance on the default instance. So something like this is possible.
var Mongoose = require('mongoose').Mongoose;
var instance1 = new Mongoose();
instance1.connect('foo');
var instance2 = new Mongoose();
instance2.connect('bar');
This is very useful when working with separate data sources, and also when you want to have a separate database context for each user or request. You will need to be careful, as it is possible to create a LOT of connections when doing this. Make sure to call disconnect() when instances are not needed, and also to limit the pool size created by each instance.
Mongoose and multiple database in single node.js project
use useDb to solve this issue
example
//product databse
const myDB = mongoose.connection.useDb('product');
module.exports = myDB.model("Snack", snackSchema);
//user databse
const myDB = mongoose.connection.useDb('user');
module.exports = myDB.model("User", userSchema);
A bit optimized(for me atleast) solution. write this to a file db.js and require this to wherever required and call it with a function call and you are good to go.
const MongoClient = require('mongodb').MongoClient;
async function getConnections(url,db){
return new Promise((resolve,reject)=>{
MongoClient.connect(url, { useUnifiedTopology: true },function(err, client) {
if(err) { console.error(err)
resolve(false);
}
else{
resolve(client.db(db));
}
})
});
}
module.exports = async function(){
let dbs = [];
dbs['db1'] = await getConnections('mongodb://localhost:27017/','db1');
dbs['db2'] = await getConnections('mongodb://localhost:27017/','db2');
return dbs;
};
I have been using this method and it works great for me until now.
const mongoose = require('mongoose');
function makeNewConnection(uri) {
const db = mongoose.createConnection(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
});
db.on('error', function (error) {
console.log(`MongoDB :: connection ${this.name} ${JSON.stringify(error)}`);
db.close().catch(() => console.log(`MongoDB :: failed to close connection ${this.name}`));
});
db.on('connected', function () {
mongoose.set('debug', function (col, method, query, doc) {
console.log(`MongoDB :: ${this.conn.name} ${col}.${method}(${JSON.stringify(query)},${JSON.stringify(doc)})`);
});
console.log(`MongoDB :: connected ${this.name}`);
});
db.on('disconnected', function () {
console.log(`MongoDB :: disconnected ${this.name}`);
});
return db;
}
// Use
const db1 = makeNewConnection(MONGO_URI_DB1);
const db2 = makeNewConnection(MONGO_URI_DB2);
module.exports = {
db1,
db2
}

Categories