How to connect to specific database with Mongoose and node? - node.js

I'm learning how to use Mongoose and there's something I don't understand - how can I connect to specific database and collection in my cluster?
I have 5 different databases and each database have few different collections
When I was using pure Mongo client - the way the show it in official documentation, I connected like that:
const MongoClient = require('mongodb').MongoClient;
const uri = process.env.mongo_connection_string;
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
const collection = client.db("database_name").collection("collection_name");
// Do some work here in the selected database and the selected collection
client.close();
});
Now I want to use Mongoose to practice. So in my app.js to establish the connection I do:
mongoose.connect(process.env.mongo_connection_string , {useNewUrlParser: true})
.then( () => console.log("Connection established"))
.catch(err => console.log(err))
Then I have created a schema for one of the objects I want to store in the database.
const mongoose = require('mongoose')
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
}
})
const User = mongoose.model('User', UserSchema)
module.exports = User
How do I associate this model with the database and the collection I need?

To connect to a specific database you can add the name in the options like this:
mongoose
.connect(db_url, {
useNewUrlParser: true,
useUnifiedTopology: true,
dbName: 'MyDatabaseName',
})
.then(() => {
console.log('Connected to the Database.');
})
.catch(err => console.error(err));

Please specify the database name in URI like link (or)
Please get the default client object with mongo URI then get the required database and collection objects.

Related

Nodejs: not getting any data while fetching data from MongoDB?

I am trying to fetch data from MongoDB by a field name - pubdate, but data is not showing neither I am getting any error!
I have field in the collection - _id, article, headline, pubdate all are String type except _id which is Objectid.
When I tried this query in Mongo query browser like - compass and studio 3t I got data -
{ pubdate: { '$gte': '2022-12-01', '$lte': '2022-12-31' } }
I am using postman to fetch data, in raw option sending POST request in JSON form.
{"fdate":"2022-12-31","tdate":"2022-12-31"}
const express = require("express");
const app = express();
const port = 3005;
const mongoose = require("mongoose");
// Connect to MongoDB using Mongoose
const url =
"mongodb://localhost:2701/db";
mongoose.connect(url, { useUnifiedTopology: true, useNewUrlParser: true });
const db = mongoose.connection;
db.on("error", console.error.bind(console, "MongoDB connection error:"));
// Define the Article schema
const articleSchema = new mongoose.Schema({
headline: String,
fulltext: String,
pubdate: String,
article_type: String,
});
const Article = mongoose.model("collectioname", articleSchema);
// Route for retrieving articles based on fromdate and todate
app.post("/articles2", (req, res) => {
let _fDate = req.body.fdate;
let _tDate = req.body.tdate;
Article.find({
pubdate: { $gte: _fDate, $lte: _tDate },
}).exec((err, articles) => {
if (err) {
console.error(err);
res.status(500).send("Error retrieving articles");
return;
}
res.send(articles);
});
});
// Start the server
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
How Will I pass the value in Postman to get the record, I am clueless as of now?
I tried map function too but no output-
let _articles = articles.map((x) => x.articleid); res.send(_articles);
Your issue is caused by Mongoose, by default, lowercasing and pluralizing the name that you pass when creating the model to determine the name of the collection it will use for the model.
In other words, when you use mongoose.model('User', UserSchema), Mongoose will take the name (User) and lowercase and pluralize it, so the collection becomes users.
If you want Mongoose to use an existing collection, or if you want to have full control of the collection name, you need to use the collection option in your schema:
const articleSchema = new mongoose.Schema({
headline: String,
fulltext: String,
pubdate: String,
article_type: String,
}, {
collection : 'article_fulltext' // the collection to use for this schema
});
const Article = mongoose.model("Article", articleSchema);
Without this option, and assume that you used article_fulltext as the model name, Mongoose would have used a collection named article_fulltexts.
Can you try logging what articles return in exec callback?
One possible issue could be that variables _fDate and _tDate are not seen as Dates by mongoose.So try wrapping them with new Date?
Article.find({
pubdate: { $gte: new Date(_fDate), $lte: new Date(_tDate) },
})

How to fetch all data only from mongoose with Nodejs

I am not able to fetch all the data from mongoose. When I tried to fetch data it create new collection name(signins) with empty, but singin collection already exists.
I don't understand what I am doing wrong here
Index.js File
const express = require("express");
const app = express();
const mongoose = require("mongoose");
mongoose
.connect("mongodb://0.0.0.0:27017/signin")
.then(() => console.log("MongoDB Connected"))
.catch((err) => console.log(err));
const User = require("./models/signin");
app.use("/", (req, res) => {
User.find({}, (err, data) => {
if (err) throw new err();
return res.json(data);
});
});
app.listen(5500, () => console.log("Port Started on 5500"));
signin
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const loginSign = new Schema({
email: { type: String, required: true },
password: { type: String, required: true },
date: { type: Date, default: Date.now },
});
module.exports = Users = mongoose.model("signin", loginSign);
Mongoose will automatically "pluralize" the name of your collection from your model name.
So mongoose.model("signin", loginSign) is creating a collection named "signins".
From the documentation: https://mongoosejs.com/docs/models.html#compiling
The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural, lowercased version of your model name.
Providing a third argument will use a collection name you specify, instead of the one mongoose creates. So in your case you could:
mongoose.model("signin", loginSign, "signin");
That said, having plural collection names is the standard, and encouraged.

How does mongoose know what collection I am accessing?

I'm having a trouble grasping a concept in Mongoose.
I'm using MongoDB atlas, got a cluster , a database and 2 collections.
users, characters.
Through a guide I've learned that a good way to write your stuff is to have a model (I use the naming schema) as a file, importing it into your Database module/class
and using it there to perform a query...
const mongoose = require("mongoose");
const process = require("./config.env");
db = () => {
return mongoose
.connect(process.env.URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: true,
})
.then((response) => {
console.log(`Connected to Databse : ${response.connection.host}`);
})
.catch((err) => {
console.log("DB_ERROR:", err);
process.exit(1);
});
};
module.exports = db;
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
});
const User = mongoose.model("User", UserSchema);
module.exports = User;
const User = require("../schemas/User");
const db = require("../config/db");
class Database {
constructor(db, collection) {
this.db = db;
this.collection = collection;
this.User = User;
}
connect() {
return db();
}
}
module.exports = Database;
one file to handle the db connection..another file as the User schema and a third file to handle every function i might use globally...
One thing I cannot wrap my mind around is
how is the findOne() function able to locate the collection I am using without me telling it what collection i want it to search in?
is it somehow translating the
const User = mongoose.model("User", UserSchema);
line and searching for "users" as well? I just can't understand the magic behind this...
what if I want to search specifically in the characters collection...?
Mongoose uses the model name, as passed when it was created: mongoose.model("User", UserSchema), converted to lower case and with an 's' appended.
For the model User it uses the collection users by default. You can change this by explicitly specifying the collection name in the schema.

"Mongo Error : Authentication failed" can't read datas from MongoDB Atlas

Today I wanted to use clusters in MongoDB Atlas to get an online DB, instead of my MongoDB local database (which worked perfectly fine),
So, I followed a mLab tutorial,
It works perfectly on writing in the database (when I auth in my website, it adds the datas in the database, when I write a message in the chat it adds the message, etc...)
But when I want to read these datas, I got :
MongoTimeoutError: Server selection timed out after 30000 ms
MongoError: Authentication failed
The connect in my server/index.js seems to work, because I got the console log :
mongoose
.connect(
`mongodb+srv://${process.env.USER}:${process.env.PASSWORD}#ofilms-demo-f9iwz.mongodb.net/test?retryWrites=true&w=majority`,
{ useNewUrlParser: true, useUnifiedTopology: true }
).then(() =>
console.log(
"working"
)
)
.catch(err => console.log(err));
but not other routes, like this one (which get all users in the database) :
const mongo = require("mongodb").MongoClient;
router.get("/getAll", function(req, res) {
console.log("get all users");
const client = new mongo(`mongodb+srv://${process.env.USER}:${process.env.PASSWORD}#ofilms-demo-f9iwz.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
});
client.connect(err => {
const collection = client.db("test").collection("users");
collection.find().toArray((err, items) => {
res.json(items);
});
client.close();
});
});
One model from Mongoose :
/* eslint-disable no-undef */
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
username: {
type: String,
required: true
},
email: {
type: String,
required: true,
lowercase: true
},
password: {
type: String,
required: true
},
firstname: String,
lastname: String,
sexe: String,
mobilePhone: String,
departement: Number,
city: String,
moviesLiked: Array,
seriesLiked: Array,
moviesDisliked: Array,
seriesDisliked: Array,
moviesFavorites: Array,
seriesFavorites: Array,
lists: Array,
creationDate: {
type: Date,
default: Date.now
},
lastConnection: Date,
isVerified: Boolean,
isAdmin: Boolean,
isModerator: Boolean,
isConnected: Boolean
});
module.exports = User = mongoose.model("users", UserSchema);
I can show you the code of other files if needed, or give you the link of the repo if someone wants it, but it's a really big project,
Thanks,
You seem to connect mongodb with both mongoose.connect() and MongoClient.connect(), one of them will be enough.
If you want to use mongoose you can connect to mongodb in your main file (index.js or app.js), and when connected to the db your server can start listening.
And you don't need to connect mongodb in your routes.
For example:
index.js (main file)
const express = require("express");
const app = express();
require("dotenv").config();
const users = require("../routes/users"); //todo: correct the users route path
app.use("/api/users", users);
mongoose
.connect(
`mongodb+srv://${process.env.USER}:${process.env.PASSWORD}#ofilms-demo-f9iwz.mongodb.net/test?retryWrites=true&w=majority`,
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then(() => console.log("working"))
.catch(err => console.log(err));
in your route: (users.js)
const express = require("express");
const router = express.Router();
const User = require("../../models/User");
router.get("/users", async (req, res) => {
const users = await User.find({});
res.send(users);
});
module.exports = router;
As you see there is no connection related code in our route, because we have already connected when the application starts.
For this code to work, you need to add your local IP to the IP whitelist IP in mongodb atlas panel. (SECURITY --> Network Access --> IP Whitelist.
Also the user you are using to connect must have read an write priveleges.
You can check your users priveleges in SECURITY --> Database Access --> MongoDB Users.

Trouble connecting to MongoDB and creating a new Collections folder through Node / Postman

I was following the tutorial of this Youtube video in order to build an API that would connect and interact with my Mongo database. The progress was going great until I got to the part referenced in the link (1:05:20).
This is the code the tutorial creator utilized.
let mongoose = require('mongoose')
const server = 'ds221609.mlab.com:21609'
const database = 'rest-api-workshop'
const user = 'username'
const password = 'password'
mongoose.connect(`mongodb://${user}:${password}#${server}/${database}`)
let CustomerSchema = new mongoose.Schema({
name: String,
email: {
type: String,
requried: true,
unique: true
}
})
module.exports = mongoose.model('Customer', CustomerSchema)
I obviously swapped around credentials with the ones for my mongodb user, but was still unable to get it to work.
Furthermore, the format given by mongodb now seems very different:
const MongoClient = require('mongodb').MongoClient;
const uri = "mongodb+srv://<username>:<password>#<databaseID>.azure.mongodb.net/admin?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
const collection = client.db("test").collection("devices");
// perform actions on the collection object
client.close();
});
My goal is to basically create a new record under the "customers" folder of my db collections. How do I accomplish this in 2019?

Resources