mongodb not erroring with wrong uri - node.js

I am having big problems trying to wrap my head around mongodb.
First of all, I tried using mongoose, but I really don't like its schemas, I want to have my own classes, and perform CRUD operations in a classic style.
So I moved on and started using mongodb. I think I already gonna give up and use MySQL, because I find their documentation very very obscure, and also no public issue tracker on github.
Anyway, my problem is that if I connect to a non existing db or to a non existing host, mongodb isn't showing any error.
My code:
const mongodb = require( 'mongodb' ),
MongoClient = mongodb.MongoClient;
let db_uri = `mongodb://${config.host}:${config.port}/${config.name}`;
MongoClient.connect( db_uri, function( err, mongoclient ) {
console.log( err );
});
Assume that config.host or config.port are not correct.
err is alway null.
Why is this ?

Mongodb does this great(and in some cases really annoying thing if you have fat fingers) where if you attempt to connect a database that doesn't exist, it will create it for you. I knew it did this in command line, but it appears it does it with this code as well. Using the insert code from the npm node instructions I was able to test and verify this.
Edit- removing example and adding something actually helpful
It may be cumbersome, but there is a way to test if a collection exists. You ask if an index exists.
const mongodb = require( 'mongodb' ),
MongoClient = mongodb.MongoClient;
var db_uri = "mongodb://localhost:27017/newDb";
MongoClient.connect( db_uri, function( err, db ) {
var collection = db.collection('documents');
collection.indexExists(0, function(err, indexExists){
});
});

Related

Database Connection using common module is not working [ mongoose and mongodb ]

I am trying to implement a common module for MongoDB connection using mongoose. and want to use the connection in other application for database operation. but facing issue when trying to use common database module. operation is halted / hanging after creating db connection. here is my codebase.
When I am using module specific dababase connection, then it is working fine, but when I am using common database connection it is hanging
Common DB Module
'use strict'
const mongoose = require('mongoose');
const DBOptions = require('./DBOption');
require("dotenv").config();
mongoose.Promise = global.Promise;
let isConnected;
const connectToDatabase = (MONGODB_URL) => {
if (isConnected) {
console.log('using existing database connection');
return Promise.resolve();
}
console.log('using new database connection');
console.log('DBOptions >> '+JSON.stringify(DBOptions));
return mongoose.connect(MONGODB_URL, DBOptions)
.then(db => {
console.log('db.connections[0].readyState >> '+db.connections[0].readyState);
isConnected = db.connections[0].readyState;
});
};
module.exports = connectToDatabase;
API Controller
const dbConnection = require('../DB/connection') // Internal Class
const DBConnection = require('as-common-util').connectToDatabase; // Common Class
/**
*
*/
app.get('/usr/alluser', async (req, res) => {
try {
//await dbConnection(process.env.MONGODB_URL) // This is working
await DBConnection(process.env.MONGODB_URL) // Code is hanging for this
let allUsers = await UserService.getAllUser()
console.log("All Users >> " + allUsers)
if (allUsers) {
return res.status(200).send(
new APIResponse({
success: true,
obj: allUsers
})
)
}
} catch (error) {
console.log(error)
}
})
It is hanging at following position
using new database connection
DBOptions >>
{"useNewUrlParser":true,"useUnifiedTopology":true,"useCreateIndex":true,"useFindAndModify":false,"autoIndex":false,"poolSize":10,"serverSelectionTimeoutMS":5000,"socketTimeoutMS":45000,"family":4}
db.connections[0].readyState >> 1
I am confused why same code is not working for common module.
This kind of pattern is not how Mongoose is meant to be used. Under the hood, Mongoose passes the underlying connection to the models in your module without the user really knowing anything about what is going on. That's why you can do magic stuff like MyModel.find() without ever having to create a model object yourself, or pass a db connection object to it.
If your db connection is in another module though, Mongoose won't be able to make those connections between your models and the MongoDB client connection since the models are no longer being registered on the mongoose object that is actually connected, and as a result, any requests you make using your models will break, since they will always be trying to connect through the object in your module.
There are other reasons why this won't, and shouldn't, work though. You're not supposed to be able to split a client. Doing so would make it unclear where communication along a client is coming from, or going to. You could change your function to make it return an established client connection. But your Mongoose models still wouldn't work. You would just be left with raw mongodb. If you want to do that, you might as well just uninstall Mongoose and use the mongodb library. Ultimately, you don't really gain anything from initializing the connection in a shared module. Initializing a connection is just a couple lines of code.
I doubt it's the connection that you want to share, rather it's the models (I'm guessing). You can put those in a shared module, and export them as a kind of connector function that injects the a given Mongoose instance into the models. See: Defining Mongoose Models in Separate Module.

How can I verify I don't need the mLab add-on for my Heroku node.js app?

After reading through the mLab -> Atlas migration plan a few times, I decided I'd try a different way. My coding background is mainly asm on mcs51 so I'm something of a n00b in the node.js/mongo/heroku world. I barely understood half of the migration process.
So I wrote a small test app following this blog entry and then used what I'd learned to modify my actual app to talk to Atlas directly. I exported the collections from the old db to JSON, then imported them into the Atlas version to recreate the database. Everything appears to be working correctly; I don't see any data going into the old db and it looks like the new Atlas db is getting all the action.
But I'm leery of deleting the mLab add-on from Heroku until I've verified that it's truly not needed any more, because I'm pretty sure that I won't be able to recreate it if it turns out I've missed something.
So my question is, how can I ensure I'm no longer using the mLab add-on? I don't really understand what it was doing for me in the first place so I'm not sure how to verify I'm not using it any more.
Here are the relevant code snippets I'm using to access the Atlas db...
function myEncode(str) { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
const ATLASURI = process.env.ATLASURI;
const ATLASDB = process.env.ATLASDB;
const ATLASUSER = process.env.ATLASUSER;
const ATLASPW = myEncode(process.env.ATLASPW); // wrapper needed to handle strong paswords...
const dbURL = "mongodb+srv://"+ATLASUSER+":"+ATLASPW+"#"+ATLASURI+"/"+ATLASDB+"?retryWrites=true&w=majority";
var GoogleStrategy = require('passport-google-oauth20').Strategy;
const {MongoClient} = require('mongodb');
const client = new MongoClient(dbURL, { useNewUrlParser: true, useUnifiedTopology: true });
var store = new MongoDBStore({uri: dbURL,collection: 'Sessions'});
var db = undefined;
client.connect(async function(err) {
if(err) {console.log("Error:\n"+String(err));}
db = await client.db(ATLASDB);
console.log("Connected to db!");
banner();
});

.find() returns empty when used with node.js and mongoose but returns data on mongo shell [duplicate]

I have tried using find and findOne and both are not returning a document. find is returning an empty array while findOne is returning null. err in both cases in null as well.
Here is my connection:
function connectToDB(){
mongoose.connect("mongodb://localhost/test"); //i have also tried 127.0.0.1
db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", function callback(){
console.log("CONNECTED");
});
};
Here is my schema:
var fileSchema = mongoose.Schema({
hash: String,
type: String,
extension: String,
size: String,
uploaded: {type:Date, default:(Date.now)},
expires: {type:Date, default:(Date.now()+oneDay)}
});
var Model = mongoose.model("Model", fileSchema);
And my query is here:
Model.find({},function(err, file) {
console.log(err)
console.log(file);
});
I can upload things to the database and see them via RockMongo but I cannot fetch them after. This my first time using MongoDB so I think I'm just missing some of the fundamentals. Any push in the right direction would be great!
The call to mongoose.model establishes the name of the collection the model is tied to, with the default being the pluralized, lower-cased model name. So with your code, that would be 'models'. To use the model with the files collection, change that line to:
var Model = mongoose.model("Model", fileSchema, "files");
or
var Model = mongoose.model("file", fileSchema);
Simply inorder to avoid pluralization complexity use this:
var Model = mongoose.model("Model", fileSchema, "pure name your db collection");
It's very confusing.[at least for me.]
Had kinda same problem. The solutions above didnt work for me. My app never returns error even if the query is not found. It returns empty array. So i put this in my code:
if(queryResult.length==0) return res.status(404).send("not found");
This issue is probably coming from the fact that you are creating a mongoose model without specifying the name of the collection.
Try changing : const Model = mongoose.model("Model", fileSchema);
To this : const Model = mongoose.model("Model", fileSchema, "NameOfCollection");
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
I had a space in 'Growing Unit' on purpose and it always returned empty array. Removing that space to become 'GrowingUnit' was the fix needed in my scenario.
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
General "hello world" issues (Sometimes this issue not related to mongoose).
Check if the collection is not really empty (mongoDB atlas screenshot).
Check for small spelling differences (Like listing instead of listings) in your collection queries commands.
Check if you use the correct URI for your connection (For example you are trying to retrieve data from a collection that exists in localhost but use mongoDB cluster (Cloud) -or- any other issue related to Connection String URI).
https://docs.mongodb.com/manual/reference/connection-string/
For me the issue was .skip(value), I was passing page=1 instead of page=0.
As I was having few records, I was getting empty array always.

Cannot fetch data from MongoDB using Mongoose [duplicate]

I have tried using find and findOne and both are not returning a document. find is returning an empty array while findOne is returning null. err in both cases in null as well.
Here is my connection:
function connectToDB(){
mongoose.connect("mongodb://localhost/test"); //i have also tried 127.0.0.1
db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", function callback(){
console.log("CONNECTED");
});
};
Here is my schema:
var fileSchema = mongoose.Schema({
hash: String,
type: String,
extension: String,
size: String,
uploaded: {type:Date, default:(Date.now)},
expires: {type:Date, default:(Date.now()+oneDay)}
});
var Model = mongoose.model("Model", fileSchema);
And my query is here:
Model.find({},function(err, file) {
console.log(err)
console.log(file);
});
I can upload things to the database and see them via RockMongo but I cannot fetch them after. This my first time using MongoDB so I think I'm just missing some of the fundamentals. Any push in the right direction would be great!
The call to mongoose.model establishes the name of the collection the model is tied to, with the default being the pluralized, lower-cased model name. So with your code, that would be 'models'. To use the model with the files collection, change that line to:
var Model = mongoose.model("Model", fileSchema, "files");
or
var Model = mongoose.model("file", fileSchema);
Simply inorder to avoid pluralization complexity use this:
var Model = mongoose.model("Model", fileSchema, "pure name your db collection");
It's very confusing.[at least for me.]
Had kinda same problem. The solutions above didnt work for me. My app never returns error even if the query is not found. It returns empty array. So i put this in my code:
if(queryResult.length==0) return res.status(404).send("not found");
This issue is probably coming from the fact that you are creating a mongoose model without specifying the name of the collection.
Try changing : const Model = mongoose.model("Model", fileSchema);
To this : const Model = mongoose.model("Model", fileSchema, "NameOfCollection");
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
I had a space in 'Growing Unit' on purpose and it always returned empty array. Removing that space to become 'GrowingUnit' was the fix needed in my scenario.
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
General "hello world" issues (Sometimes this issue not related to mongoose).
Check if the collection is not really empty (mongoDB atlas screenshot).
Check for small spelling differences (Like listing instead of listings) in your collection queries commands.
Check if you use the correct URI for your connection (For example you are trying to retrieve data from a collection that exists in localhost but use mongoDB cluster (Cloud) -or- any other issue related to Connection String URI).
https://docs.mongodb.com/manual/reference/connection-string/
For me the issue was .skip(value), I was passing page=1 instead of page=0.
As I was having few records, I was getting empty array always.

Mongoose always returning an empty array NodeJS

I have tried using find and findOne and both are not returning a document. find is returning an empty array while findOne is returning null. err in both cases in null as well.
Here is my connection:
function connectToDB(){
mongoose.connect("mongodb://localhost/test"); //i have also tried 127.0.0.1
db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", function callback(){
console.log("CONNECTED");
});
};
Here is my schema:
var fileSchema = mongoose.Schema({
hash: String,
type: String,
extension: String,
size: String,
uploaded: {type:Date, default:(Date.now)},
expires: {type:Date, default:(Date.now()+oneDay)}
});
var Model = mongoose.model("Model", fileSchema);
And my query is here:
Model.find({},function(err, file) {
console.log(err)
console.log(file);
});
I can upload things to the database and see them via RockMongo but I cannot fetch them after. This my first time using MongoDB so I think I'm just missing some of the fundamentals. Any push in the right direction would be great!
The call to mongoose.model establishes the name of the collection the model is tied to, with the default being the pluralized, lower-cased model name. So with your code, that would be 'models'. To use the model with the files collection, change that line to:
var Model = mongoose.model("Model", fileSchema, "files");
or
var Model = mongoose.model("file", fileSchema);
Simply inorder to avoid pluralization complexity use this:
var Model = mongoose.model("Model", fileSchema, "pure name your db collection");
It's very confusing.[at least for me.]
Had kinda same problem. The solutions above didnt work for me. My app never returns error even if the query is not found. It returns empty array. So i put this in my code:
if(queryResult.length==0) return res.status(404).send("not found");
This issue is probably coming from the fact that you are creating a mongoose model without specifying the name of the collection.
Try changing : const Model = mongoose.model("Model", fileSchema);
To this : const Model = mongoose.model("Model", fileSchema, "NameOfCollection");
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
I had a space in 'Growing Unit' on purpose and it always returned empty array. Removing that space to become 'GrowingUnit' was the fix needed in my scenario.
const growingUnit= mongoose.model('Growing Unit', growingUnitSchema);
General "hello world" issues (Sometimes this issue not related to mongoose).
Check if the collection is not really empty (mongoDB atlas screenshot).
Check for small spelling differences (Like listing instead of listings) in your collection queries commands.
Check if you use the correct URI for your connection (For example you are trying to retrieve data from a collection that exists in localhost but use mongoDB cluster (Cloud) -or- any other issue related to Connection String URI).
https://docs.mongodb.com/manual/reference/connection-string/
For me the issue was .skip(value), I was passing page=1 instead of page=0.
As I was having few records, I was getting empty array always.

Resources