Mongodb not creating database - node.js

I cant create my database 'sms-dev' in mongodb after starting the server but in my console it was printing connected to mongo successfully.I kept my db module inside models folder as db.js and export that module in another file(config.js) inside models folder
Here is the code in db.js file
var db = {
// Connects to mongoDB
connect: function(url, options) {
mongoose.connect(url, options);
mongoose.connection.on('open', function(){
console.log("Connected to mongo successfully");
});
mongoose.connection.on('disconnect', function(){
console.log("Mongo disconnected");
});
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
}
}
module.exports = db;
and my config.js file is
exports.database = {
url: 'mongodb://127.0.0.1:27017/sms-dev',
options: {
db: { native_parser: true,safe:true },
server: { poolSize: 10 }
}
}
I connected this db in server.js as
var dbcon = process.env.MONGOLAB_URI || config.database.url;
db.connect(dbcon, config.database.options);

This line:
As soon as you create a record with that connection
From this answer.
Did it for me. In my case I had to manually:
Create the database
Create a collection
Create a record in the collection
And then everything was good again.

You should keep your db connection very simple as you are using mongoose.
mongoose.connect should only be called once. That will create the default connection pool for your application.
//db.js
// Bring Mongoose into the app
var mongoose = require( 'mongoose' );
// Create the database connection
mongoose.connect('mongodb://127.0.0.1:27017/sms-dev');
// CONNECTION EVENTS
// When successfully connected
mongoose.connection.on('connected', function () {
console.log('Mongoose default connection open to ' + 'mongodb://127.0.0.1:27017/sms-dev');
});
// If the connection throws an error
mongoose.connection.on('error',function (err) {
console.log('Mongoose default connection error: ' + err);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
});
// If the Node process ends, close the Mongoose connection
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
You can then easily use the db connection by require mongoose in your files.
//users.js
var mongoose = require( 'mongoose' ),
Users = mongoose.model('users');

It seems that my mongodb was not locked properly so i remove the mongodb.lock file and run with -repair option

Once you ll save data in the database
,You can see the Database by running command
show dbs
const mongoose=require("mongoose")
mongoose.connect('mongodb://localhost:27017/username_db');
var db=mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("connected successfully")
});
const Schema=mongoose.Schema;
const myschema=new Schema({
name:String,
},{
timestamps:true
});
var model=mongoose.model('myname',myschema);
var data=new myname({
name: 'xyz',
})
data.save((err)=>{
res.send("Error in saving to database");
})

Once you ll save data in the database
,You can see the Database by running command
show dbs
const mongoose=require("mongoose")
mongoose.connect('mongodb://localhost:27017/username_db');
var db=mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("connected successfully")
});
const Schema=mongoose.Schema;
const myschema=new Schema({
name:String,
},{
timestamps:true
});
var model=mongoose.model('myname',myschema);
var data=new myname({
name: 'xyz',
})
data.save((err)=>{
res.send("Error in saving to database");
})

This is quite old Post, to which I am updating using latest packages - This solution will fix this mongo db connection issue on following version of env.
Node version - 11.5.0 (node -v)
NPM. - 6.4.1(npm -v)
Typescript. - 3.8.3(tsc -v)
Mongodb. - 5.9.15 (package.json)
Following are the steps need to take care in order to fix this -
1. First of all verify all changes in .ts file will be reflecting changes in corresponding .js file. As it was issue with my code it was not being updated.
Run following command and verify .js file
tsc --build tsconfig.json
If js file is not being updated simply delete.js file and run above command. It's pretty simple fix but some time we overlook for it.
Since it's typescript code. So need to copy past below code for verification.
Import * as m from 'mongoose';
export class UserControl {
RegisterUser(){
Const uri = "mongodb://127.0.0.1:27017/User";
m.connect(uri,
{useNewUrlPaerser:true,
useUnifiedTopology:true,
useFindAndModify:true,
useCreateIndex:true });
Let db = m.connection;
Db.once("open",async() =>.
{console.log(connected)});
Db.once("error",async() =>
{console.log(error)});
Const userSchema = new m.schema({
FirstName:string,
Last name:string
});
Const User = m.model('users', userSchema);
Const user = new User({
FName:Andy,
LName:Pat });
Const result = await user.save();
Console.log(result);
}
Run your solution by npm start.
Verify if db collection created?
If not.
First create db with name as "User" in mongodb
Using mongo db compass.
And than try. Still not able to see the collection.
Now need to start two separate console terminal.
go to folder and executive mongo
c:\program file\MongoDb\server\4.2\bin> mongo.exe
on another terminal type mongod ,
it will start your mongo Damon.
Now try. Since this above step will stable connection and show 1 connection active.
Hope this update help.

If you are using Mongoose or MongoClient to connect the mongodb database you will see the database created after you save the first document to the database.
e.g.: the below code will only show connection was successful but it does not create the database 'mydb'
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mydb')
.then(() => console.log('Connected to MongoDB...'))
.catch(err => console.error('Could not connect to MongoDB...', err));
The databse 'mydb' is created only when you save first document record.
const courseSchema = new mongoose.Schema({
name: String,
author: String,
tags: [String],
date: {type: Date, default: Date.now},
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema);
async function createCourse(){
const course = new Course({
name: 'Some Course',
author: 'My Name',
tags: ['JavaScript', 'backend'],
isPublished: true
});
const result = await course.save();
console.log(result);
}
createCourse();

This is a duplicate of:
Mongo db that does not exist but shows up in connection
If you insert data your database will be created.

Related

Unable to Connect to the MongoDB Database

Using the MongoDb and Mongoose for the first time to store the data of my app.js file. When I run the app.js then it throws this error after a while -> MongooseError: Operation peoples.insertOne() buffering timed out after 10000ms.
import mongoose from "mongoose";
mongoose.set("strictQuery", false);
mongoose.connect(
"mongodb://localhost:27017/peopleDB",
{ useNewUrlParser: true },
(err) => {
if (err) console.log(err);
else console.log("MongoDB is connected");
}
);
const peopleSchema = new mongoose.Schema({
name: String,
age: Number,
});
const People = new mongoose.model("People", peopleSchema);
const people = new People({ name: "John", age: 37 });
people.save();
this is the code that I wrote
After a lot of searching for the solution got to know that the connection was not made, if you are using the node the latest node.js version then replace the "localhost" with "127.0.0.1" and then try running the app.js
Create model name as "person", since people is already plural, and it may cause an error.
And make sure you run mongod server in the background using git

Mongoose connected to mongoDB but have not initialized the database

My connection code:
const mongoose = require("mongoose");
//ES6 Promise
mongoose.Promise = global.Promise;
//connect to mongoDB
mongoose.connect("mongodb://localhost/smslist", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
mongoose.connection
.once("open", function () {
console.log("Connected to database successfuly");
})
.on("error", function (error) {
console.log(`DB Connection error:`, error);
});
The mongod server terminal shows that the connection is successfull
2020-04-27T15:35:24.500+0300 I NETWORK [listener] connection accepted from 127.0.0.1:61286 #1 (1 connection now open)
2020-04-27T15:35:24.506+0300 I NETWORK [conn1] received client metadata from 127.0.0.1:61286 conn1: { driver: { name: "nodejs|Mongoose", version: "3.5.6" }, os: { type: "Windows_NT", name: "win32", architecture: "x64", version: "10.0.18362" }, platform: "'Node.js v12.16.2, LE (unified)", version: "3.5.6|5.9.10" }
The node terminal also prints
Connected to database successfuly
But when I try to use a mongoDB UI like robomongo/studio 3t/mongodb compass community, I will not see a database named smslist as expected.
I also realized that if I close the db server terminal the node terminal still shows connected to database successfully and not DB Connection error:, error as expected.
any idea?
If you haven't created any Model yet in this "smslist" database then you can not see any thing about this
You need to create some Model for this "smslist" database then you can see this in your db.
I agree it depends on the code that follows the above.
I've been working through a tutorial on this.
Here is the code and my notes on what finally worked.
// from scratch tutorial
// WORKS!!!!
//require mongoose - works
const mongoose = require('mongoose');
//define constant - works
const url = 'mongodb://127.0.0.1:27017/fruit'
// connect to datbase works as evidenced by message
mongoose.connect(url, { useNewUrlParser: true });
const db = mongoose.connection
db.once('open', _ => {
console.log('Database connected:', url)
});
db.on('error', err => {
console.error('connection error:', err)
});
//above works!! but do not see new database in mongodb
//now add schema
const Schema = mongoose.Schema
// define schema
fruitSchema = new Schema({
name: String,
rating: Number,
review: String
});
// create the model - or "collection" use singular - mongoose makes it plural
// inside database
const Fruit = mongoose.model("Fruit", fruitSchema);
//now create the document from the model (note upper and lower case)
const fruit = new Fruit({
name: "Pear",
rating: 10,
review: "good with Brie"
});
fruit.save();
//close the connection works but causes an error when trying to add a document
// mongoose.connection.close();

MongoDB watch() to observe change in Database with NodeJS and Mongoose

I am trying to watch my mongodb. whenever a change occurs I want to apply an action. This is what I have tried
var mongoose = require('mongoose');
//mongoose.connect('mongodb://localhost/test');
mongoose.Promise = global.Promise
mongoose.connect('mongodb://localhost:27017')
mongoose.connection.createCollection('people');
const Person = mongoose.model('Person', new mongoose.Schema({ name: String }));
Person.watch().
on('change', data => console.log(new Date(), data));
console.log(new Date(), 'Inserting doc');
Person.create({ name: 'john doe' });
console.log(new Date(), 'Inserted doc');
But I am getting the following error
node_modules/mongodb/lib/utils.js:132
throw err;
^
MongoError: $changeStream may not be opened on the internal admin
database
How can I fix this ?
Change streams in MongoDB requires a replica set to function.
According to Mongoose docs:
To connect to a replica set you pass a comma delimited list of hosts
to connect to rather than a single host.
mongoose.connect('mongodb://[username:password#]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]' [, options]);
Full example
const { ReplSet } = require('mongodb-topology-manager');
const mongoose = require('mongoose');
run().catch(error => console.error(error));
async function run() {
// Make sure you're using mongoose >= 5.0.0
console.log(new Date(), `mongoose version: ${mongoose.version}`);
await setupReplicaSet();
// Connect to the replica set
const uri = 'mongodb://localhost:31000,localhost:31001,localhost:31002/' +
'test?replicaSet=rs0';
await mongoose.connect(uri);
// For this example, need to explicitly create a collection, otherwise
// you get "MongoError: cannot open $changeStream for non-existent database: test"
await mongoose.connection.createCollection('Person');
// Create a new mongoose model
const personSchema = new mongoose.Schema({
name: String
});
const Person = mongoose.model('Person', personSchema, 'Person');
// Create a change stream. The 'change' event gets emitted when there's a
// change in the database
Person.watch().
on('change', data => console.log(new Date(), data));
// Insert a doc, will trigger the change stream handler above
console.log(new Date(), 'Inserting doc');
await Person.create({ name: 'Axl Rose' });
console.log(new Date(), 'Inserted doc');
}
// Boilerplate to start a new replica set. You can skip this if you already
// have a replica set running locally or in MongoDB Atlas.
async function setupReplicaSet() {
const bind_ip = 'localhost';
// Starts a 3-node replica set on ports 31000, 31001, 31002, replica set
// name is "rs0".
const replSet = new ReplSet('mongod', [
{ options: { port: 31000, dbpath: `${__dirname}/data/db/31000`, bind_ip } },
{ options: { port: 31001, dbpath: `${__dirname}/data/db/31001`, bind_ip } },
{ options: { port: 31002, dbpath: `${__dirname}/data/db/31002`, bind_ip } }
], { replSet: 'rs0' });
// Initialize the replica set
await replSet.purge();
await replSet.start();
console.log(new Date(), 'Replica set started...');
}
Full example excerpted from https://thecodebarbarian.com/stock-price-notifications-with-mongoose-and-mongodb-change-streams
You can’t, change stream cursor is not available on system collections, or any collections in the admin, local, and config databases. You could try configuring your database structure to not be an admin dB.
Mongodb changeStreams doc

Is it necessary to open MongoDB connection every time I want to work with the DB?

In the example I am working with is this code:
//lets require/import the mongodb native drivers.
var mongodb = require('mongodb');
//We need to work with "MongoClient" interface in order to connect to a mongodb server.
var MongoClient = mongodb.MongoClient;
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/my_database_name';
// Use connect method to connect to the Server
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established to', url);
// Get the documents collection
var collection = db.collection('users');
//Create some users
var user1 = {name: 'modulus admin', age: 42, roles: ['admin', 'moderator', 'user']};
var user2 = {name: 'modulus user', age: 22, roles: ['user']};
var user3 = {name: 'modulus super admin', age: 92, roles: ['super-admin', 'admin', 'moderator', 'user']};
// Insert some users
collection.insert([user1, user2, user3], function (err, result) {
if (err) {
console.log(err);
} else {
console.log('Inserted %d documents into the "users" collection. The documents inserted with "_id" are:', result.length, result);
}
//Close connection
db.close();
});
}
});
As you may see, he is doing an operation in the connect function. I would like to keep it modular and separate the connection from DB operations.
My suggestion would be to make a singleton on db variable and reuse that one. At least that's what I would do in Java to which I am used to.
However, I am not sure as in the example he hasn't suggested anything like that.
I would recommend against maintaining one connection if you want any kind of scalability.
There are a number of options for connection pooling, etc, but most folks who spend any time at all with Node and MongoDB end up moving to Mongoose at some point.
In addition to adding a nice schema layer, it offers connection abstraction so that you can default to a shared connection by calling mongoose.connect(), or you can create multiple connections or participate in connection pooling by calling mongoose.createConnection(). In both cases, you call it without a callback, and the mongoose machinery will defer subsequent calls to the module until after the connection is established, so that your code doesn't have to care.
Something like your use case might look like so:
// in your app.js or server.js file
var mongoose = require('mongoose');
mongoose.connect(config.db.url); // assuming you have some module that handles config variables
Then in ./models/user.js
const mongoose = require('mongoose'),
Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
age: Number,
roles: [String]
});
mongoose.model('User',UserSchema);
finally, in lets say a seed function to create your initial batch of users:
const mongoose = require('mongoose'),
User = mongoose.model('User');
// create some users
var user1 = new User({name: 'modulus admin', age: 42, roles: ['admin', 'moderator', 'user']});
var user2 = new User({name: 'modulus user', age: 22, roles: ['user']});
user1.save(console.log);
user2.save(console.log);
I believe maintaining a single connection is the best as mentioned in another thread:
The primary comitter in node-mongodb-native says
You open do MongoClient.connect once when your app boots up and reuse the db object. It's not a singleton connection pool each .connect creates a new connection pool. So open it once an[d] reuse across all requests.
Say on server start initiate the mongo connection.
Server.js:
...
var db = require('./db');//require db.js
db.openMongoConnection(function(error)
{
if(error)
{
console.log(error);
console.log("cannot make the connection with database");
}
else
{
server.listen(7400);//say ur server listening on 7000 port
}
}
db.js
var db1;
var MongoClient = require('mongodb').MongoClient;
exports.openMongoConnection = function(callback)
{
MongoClient.connect(<YourUrl1>,function(err,dbInstance)
{
if(err)
{
callback(err);
}
else
{
db1 = dbInstance;
callback(null);
}
});
};
exports.getCollection = function(collectionName, callback){
dbInstance.collection(collectionName, function(err, collectionInstance){
if(err)
{
callback(err);
}
else
{
callback(null, collectionInstance)
}
});
}
Then you can call the getCollection to use at anytime by requiring dbInsance

Getting list of all databases with Mongoose

There are some similar questions but all of them involves using the MongoDB NodeJS driver instead of Mongoose ODM.
I read the docs but couldn't find such functionality.
You can't directly get the list from the connection provided by mongoose, but it's easy to do with the mongo Admin object as it contains a function called listDatabases:
var mongoose = require('mongoose')
, Admin = mongoose.mongo.Admin;
/// create a connection to the DB
var connection = mongoose.createConnection(
'mongodb://user:pass#localhost:port/database');
connection.on('open', function() {
// connection established
new Admin(connection.db).listDatabases(function(err, result) {
console.log('listDatabases succeeded');
// database list stored in result.databases
var allDatabases = result.databases;
});
});
A very modern approach to get list of all mongo databases using mongoose (version 6.10.*) is to Create a mongoose connection to connect to Mongo's admin database and make sure you have an admin user.
Mongoose object is a very complex object. To list the db's :
const connection = `mongodb://${encodeURIComponent(username)}:${encodeURIComponent(password)}#${hostname}:${port}/admin`
mongoose is a very complex object with promises for executing several functions. to list the db's :
mongoose.connect(connection, { useNewUrlParser: true , useUnifiedTopology: true }).then( (MongooseNode) => {
/* I use the default nativeConnection object since my connection object uses a single hostname and port. Iterate here if you work with multiple hostnames in the connection object */
const nativeConnetion = MongooseNode.connections[0]
//now call the list databases function
new Admin(nativeConnetion.db).listDatabases(function(err, results){
console.log(results) //store results and use
});
})
Result:
{ databases:
[ { name: 'admin', sizeOnDisk: 184320, empty: false },
{ name: 'config', sizeOnDisk: 73728, empty: false },
{ name: 'local', sizeOnDisk: 73728, empty: false },
{ name: 'test', sizeOnDisk: 405504, empty: false } ],
totalSize: 737280,
ok: 1 }
If someone is looking for answers from the latest version of Mongoose and Mongodb, the below code can be used.
import mongoose from 'mongoose';
mongoose.set('strictQuery', true);
mongoose.connect('mongodb://localhost:27017/mydb', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
// Check DB Connection
db.once('open', () => {
(async () => {
const data = await mongoose.connection.db.admin().command({
listDatabases: 1,
});
console.log(data);
})();
console.log('Connected to MongoDB');
});
// Check for DB errors
db.on('error', (err) => {
console.log('DB Connection errors', err);
});
export default mongoose;
If you want to get the database list on your other functions, make sure the connection is established first and also make sure the user has admin access and then just do the below query. This is a sample from my API router.
// Get all databases
router.get('/database/get', async (req, res) => {
try {
const data = await mongoose.connection.db.admin().command({
listDatabases: 1,
});
if (data && data !== null) {
res.status(200).send({ data: data });
return;
}
res.status(200).send({ data: null, message: 'Data not found' });
} catch (e) {
// eslint-disable-next-line no-console
console.log(e);
res.status(500).send(e.message);
}
});
Try running this code. Original take from Gist.

Resources