Mongoose MongoDB in Production - node.js

I'm having a really weird issue where Mongoose will not perform queries against collections outside of the Model definition file when NODE_ENV=production, even when connecting to localhost.
db/default.js
const mongoose = require('mongoose');
module.exports = {
connect(url) {
mongoose.connect(url);
}
};
app.js
const db = require('./db/default');
db.connect(config.get('mongoDB.uri'));
User.model.js
const mongoose = require('mongoose');
const schema = new mongoose.Schema({
// ...
});
const User = mongoose.model('User', schema);
module.exports = User;
test.js
// This file is required by a route
const User = require('./models/User.model');
User.find({})
.then(response => console.log(response))
.catch(err => console.log(err));
All of this works absolutely fine when NODE_ENV=dev, but as soon as NODE_ENV=production, the User.find({})... doesn't run. No errors, no success, it just doesn't run.
If I log the User = require('./models/User.model'), it is a Mongoose object.
If I run the User.find({})... code inside the User.model.js file whilst in production, that also works.
I am utterly befuddled as to why this does not work.

Related

Empty on collection

I have created database and have make one collection with the name staff there, I have put 3 data and it is showing on mongodb compass. But will try to fetch staff I got empty array. I am baby with this mongo db envirnment so I am unknow where did I get mess on my code.
Here, I have two files. one server.js which is main file and another is model file
server.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const Staff = require("./staff");
const dbname = "mydbname";
const dbpass = "mypassword";
const dbuser = "meuser";
mongoose.connect(
"mongodb+srv://"+dbuser+":"+dbpass+"#cluster0.ovjvl.mongodb.net/"+dbname+"?retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.warn("db connection done"))
.catch((error) => console.warn("DB Not Connect", error));
Staff.find({},(err,data)=>{
if(err) console.warn(err)
console.warn("Data :",data)
})
staff.js
const mongoose = require("mongoose");
let staffSchema = new mongoose.Schema({
_id : mongoose.Schema.Types.ObjectId,
name:String,
designation:String,
gender:String,
salary:mongoose.Schema.Types.Decimal128,
skills:mongoose.Schema.Types.Array})
module.exports = mongoose.model('staff',staffSchema)
While I run my app I got below ouput
db connection done
Data : []
But am expecting some data on array.
Note : For security reason, I have mention dbname,user & password is fake.

MongooseError: Operation `users.findOne()` buffering timed out after 10000ms

This is my connection file
const connectDB = async () =>{
const conn = await new mongoose("mongodb+srv://nikunj:gadia7420#cluster0.94xph.mongodb.net/myFirstDatabase?retryWrites=true&w=majority",
{
usenewurlparser:true,
usecreateindex:true,
usefindmodify:true,
useunifiedtropology:true,
urlencoded:true
})
}
module.exports = connectDB;
this is my models file
const userSchema = new mongoose.Schema({
username:{
type:String,
required:true
},
avatar:{
type:String,
},
email:{
type:String,
required:true
},
password:{
type : String,
required:true
}
});
module.exports = mongoose.model('user',userSchema);
this file will insert or take information from database for registeration
const express = require('express');
const router = express.Router();
const User = require('../models/user');
const bcrypt= require('bcrypt');
router.post('/register',async(req,res,next)=>{
const {username,email,password}=req.body;
try{
let user_exist = await User.findOne({email:email});
if(user_exist){
success="false";
msg="user already exist";
} else {
//importing data to models
let user = new User();
user.username = username;
user.email = email ;
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password,salt),
user.avatar = "https://gravatar.com/avatar/?s=200&d=retro"
await user.save();
res.json({
sucess:true,
user:user,
msg:"user registered"
})
}
}
catch(err){
console.log(err);
}
});
module.exports = router;
this is my main file (server.js )
const express = require('express');
const morgan = require('morgan');
const colors = require('colors');
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const connectDB = require('./config/db');
//creating main platform
connectDB;
console.log(mongoose.connection.readyState);
const app = express();
app.use(morgan('dev'));
dotenv.config({
path:'./config/config.env'
})
app.use(express.json({}))
app.use(express.json({
extended:true
}))
//creating server
app.use('/api/todo/auth',require('./routes/user'));
const Port = process.env.port;
app.listen(Port,
console.log(`listening on port :${Port}` .red.underline.bold));
//creating req,res platform
but after running this it shows error while giving post request
MongooseError: Operation `users.findOne()` buffering timed out after 10000ms
at Timeout.<anonymous> (D:\nikunj\Programming\todoapp\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:185:20)
at listOnTimeout (node:internal/timers:556:17)
at processTimers (node:internal/timers:499:7)
pls find a solution for this. thanks .sorry if it is a silly or wrong question because I am new to this nodejs
Connect to your database 1st and after that start your server.
You're trying to query the database without connecting to your database.
https://mongoosejs.com/docs/connections.html#buffering
Mongoose lets you start using your models immediately, without waiting for mongoose to establish a connection to MongoDB.
That's because mongoose buffers model function calls internally. This buffering is convenient, but also a common source of confusion. Mongoose will not throw any errors by default if you use a model without connecting.
connectDB()
.then(() -> {
app.listen(Port, console.log(`listening on port :${Port}` .red.underline.bold));
}).catch((e) => {
console.log(e);
})
You're not calling the function connectDB
Turn on your Mongo Server and connect to your database before you attempt to write to it.
In my case I am using a monorepo, one package initiates the server and another contains the mongoose models.
One of the packages had a different mongoose version on it's package.json's dependencies.
The problem was fixed after making sure both packages had the same version of mongoose and then running yarn at the root of the monorepo to relink dependencies properly.
For anyone wondering, I'm able to use mongoose on two different packages in a monorepo since mongoose is basically a singleton class, meaning that it will usually try to use a pre-existing instance of mongoose wherever it is mentioned without initialization.
Having two versions of mongoose breaks this singleton functionality since (as far as Node is concerned) the instance on the server was created using a different mongoose package than the one on my models package.
TL;DR Make sure any packages in your monorepo depending on mongoose have the same version of mongoose in their respective package.json files.
This question has already been answered, however when I encountered with the same problem, the cause was very different. For some reason I put Mongodb connection URI inside quotes in config vars. Never do that. When I removed the quotes, everything worked just fine.
I faced this problem at mongoose v "^6.3.4" and when I removed my IP from network access on sidebar on mongodb and added it again it worked
I faced this problem at mongoose v "^6.3.4" and when I removed my IP
from network access on sidebar on mongodb and added it again it worked
This worked for me too. I removed my ip and selected "ALLOW ACCESS FROM ANYWHERE" option on the network access page and it worked.
(I think it is safe: "Allow access from anywhere" MongoDB Atlas)

Get existing document from MongoDB with Mongoose

I have an existing document on MongoDB atlas that I need to get in its entirety. When I try my current code I get a socket timeout, i.e. it keeps buffering.
There is only one document in my collection.
My theory is that the error is in my Mongoose Schema, but I don't know what to put there since I don't want any "filters", I want everything.
The name of the collection in Atlas is Playstation and the id of the document I want to get is: 5f5e2d281386efc27bb3ce45
const express = require('express')
const router = express.Router()
const Playstation = require('../models/playstation')
//Getting All
router.get('/', async (req, res) => {
try {
const playstations = await Playstation.findById("5f5e2d281386efc27bb3ce45")
res.json(playstations)
} catch (err) {
res.status(500).json({ message: err.message })
}
})
module.exports = router;
My schema & model:
const mongoose = require('mongoose')
const playstationSchema = new mongoose.Schema({
})
module.exports = mongoose.model('Playstation', playstationSchema)
I believe the problem is your mongoose schema. What you want is a schemaless collection, since you dont want to define the schema, and you want everything in the document, you can define the collection as schema-less, with strict:false option in your mongoose schema;
Try this:
const mongoose = require('mongoose')
const playstationSchema = new mongoose.Schema({
},{ strict : false })
module.exports = mongoose.model('Playstation', playstationSchema);
You can read more about this option on Mongoose Documentation

TypeError: connectDb is not a function?

I am new to express and node while I connecting mongodb from mongoose to localhost I get an error like TypeError: connectDb is not a function?
src/models/index
const mongoose = require("mongoose");
const User = require("./user");
const Message = require("./message");
const connectDb = () =>
mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true });
const models = { User, Message };
exports = { connectDb };
module.exports = models;
src/index
// .... Some code here
const { connectDb } = require("./models");
// .... Some code here
connectDb()
.then(async () => {
app.listen(process.env.PORT);
})
.catch(error => console.error(error));
exports = { connectDb };
this statement is not correct. Its not exporting the connectDb function.
if you want to use exports keyword to export connectDb function, you have to do it as
exports.connectDb = () => mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true });
or simply
exports.connectDb = connectDb;
If you want to export multiple things, you can add multiple properties to exports object
to export models, you can do
exports.models = models;
Now this file will export an object that has two properties on it, connectDb and models
Another way to export multiple things is
module.exports = {
connectDb,
models
};
this will also export an object containing two properties, connectDb and models
You are actually doing a weird thing. exports variable is set to point to module.exports, so when u change its reference by doing exports = { connectDb } you are actually breaking that variable's reference, so it's not exporting anything. Next thing u do is exporting ur models, which is correct, but your connectDb is actually not being exported, so you can not use it in your second file. I guess you want to export both, so actually there are some ways to achieve that. Here you have two valid options, first one using the spread operator with module.exports and second one using exports and not changing its reference but it's properties, so it keeps working correctly:
module.exports = {
...models,
connectDb
}
exports.connectDb = connectDb
exports.User = User
exports.Message = Message

How does mongoose model connect with mongodb?

I have structured a user collection using mongoose.model().This model exist in seperate file called as model\user.js. The mongodb connection instance (using mongoose) exist in seperate file db\mongoose.js. Both of these files are imported into server.js to work with web application.
var express = require('express');
var bodyParser = require('body-parser');
var {mongoose} = require('./db/mongoose');
var {User} = require('./models/user');
var app = express();
app.use(bodyParser.json());
app.post('/todos', (req, res) => {
var user = new User({
text: req.body.text
});
user.save().then((doc) => {
res.send(doc);
}, (e) => {
res.status(400).send(e);
});
});
app.listen(3000, () => {
console.log('Started on port 3000');
});
module.exports = {app};
The {mongoose} and {User} seems to be a separate entities and model\user.js didn't import ./db/mongoose.js as well . The user model being static content , how does user.save() connects with db and save the document?
First of all let me tell you what is happening in your project.
in Mongoose file:
You have DB connection with Mongoose.
Now Mongoose has your DB connection.
That is the reason it is imported in server.js file.
Secondly, in you model/user.js you have
Declared Schema using Mongoose.
user.save method.
When you use Mongoose here (or any DB related query), it points to your connected DB. Which does not require any explicit connection written in some file.
For more details read Mongoose Docs.
Hope I cleared your thoughts.

Resources