How should in right way connecting MongoDB in Nodejs? - javascript

Hello i am new in Nodejs & MongoDb.
I created controllers for API where i want create new items in MongoDB, edit, search items.
Now i am connecting to MongoDB via mongoose in main file server.js.
But i need that i can create, edit in editor.js.
I tried to export mongoose module, but it was unsuccessfull.
How i can do this in right way?
my structure
`editor.js` file - where i want have access to database
const models = require('./../models');
const client = require('./../../server');
const mongoose = require('mongoose');
let db;
// const db = client.db('todo');
module.exports = {
getNewsById: async (req, res) => {
console.log(req.params);
// console.log(req);
res.send({oK: 'ok'});
},
createNews: async (req, res) => {
const newItem = req.body;
newItem['publishedAt'] = Date.now();
console.log('HERE', client);
console.log('HERE2', client.db.collection('test').insertOne({
item: 'canvas',
qty: 100,
tags: ['cotton'],
size: { h: 28, w: 35.5, uom: 'cm' }
}));
}
}

In editor.js after importing mongoose, you can simply load your model using -
const db = require('mongoose');
const testModel = db.model('test');
And then you can call your db queries similar to -
testModel.insert(...);
testModel.find();
Once you have built your model using mongoose, it is available in the application. You just need to get it through mongoose.
If you need more help, you can refer to my sample project at https://github.com/kravigupta/nodejs-express-mongo-auth

For every new developer who is learning node.js, the first thing they go with the MongoDB connection with the node.js.
I will suggest you keep the MongoDB connection URL, username and password in a separate file say it db.config.js file and then import that file into you server.js or app.js or main file of your node.js and then connect mongo with the try catch block to handle the error. IF you need to learn in more details then you can refer to this link.

Related

MongoDB Atlas with NodeJS using Mongodb is not connecting

I'm getting an error when I'm trying to connect with MongoDB, error pointed toward connect while it's keyword itself. I didn't know what the issue here.
Error is :
mongodb.connect(
^
TypeError: mongodb.connect is not a function
let express= require('express')
let mongodb= require('mongodb').mongodb
let app = express()
let db
let connectionString = 'mongodb+srv://admin:admin#cluster0.sfis6s3.mongodb.net/ToDoApp?retryWrites=true&w=majority'
mongodb.connect(
connectionString,{useNewUrlParser: true}, function(err, client){
db = client.db()
})
app.use(express.urlencoded({extended:false}))
I think the reason is for that you must import MongoClient class
const MongoClient = require("mongodb").MongoClient;
reference:
connect is not a function when connecting to mongodb

Connecting to MongoDB database

I am trying to connect to a MongoDB database.I have followed all the steps here https://youtu.be/EcJERV3IiLM but am getting an error.
The index.js file looks like this,
const dotenv = require('dotenv')
dotenv.config()
const mongodb = require('mongodb')
mongodb.connect(process.env.CONNECTIONSTRING, async function(err,client){
const db = client.db()
const results = await db.collection("student").find().toArray()
console.log(results)
The error I get is,
mongodb.connect is not a function
So it seems to be reading as far line 5:9 which is mongodb.connect in index.js and just stops.
I put this file index.js beside the .env file and beside that .gitignore which contains the the .env file. The .env file has the code which I copied from the Mongodb AtlSAS Cloud Service.
I also created a user and and autogenerated and saved a password. Both of which I placed in the string. And I put in the string the name of the database name "blah" The table/document is called "student". That's in the index.js code above. So the database name and the document name are blah.student.
I documented what I tried here, http://www.shanegibney.com/shanegibney/mongodb-setup/
The tutorial video is here, https://youtu.be/EcJERV3IiLM
I am on Ubuntu Linux.
I am currently running index.js in the terminal in a directory called mongostack, with
node index.js
but should I use,
nodemon index.js
And for this should I install nodemon and how do I do that?
Do I need to download it first and if so where do I get it?
I think you need to get MongoClient. Try changing:
const mongodb = require('mongodb')
to:
const mongodb = require('mongodb').MongoClient;
You have to create a MongoClient see https://www.mongodb.com/docs/drivers/node/current/quick-start/
const { MongoClient } = require("mongodb");
const uri = process.env.CONNECTIONSTRING;
const client = new MongoClient(uri);
async function run() {
await client.connect();
const db = client.db("yourdb")
const results = await db.collection("student").find().toArray()
console.log(results)
}
run();

ExpressJS: Best way to separate routes and accepting params?

I made a Express.js system where the files in the /routes folder are acting as a classic route (but with one file per route)
Example: /routes/get/user.js will be accessible with http://localhost:8080/user (the /get is to separate methods, it can be /post, /put...)
Here's my entire index.js file: https://pastebin.com/ALtSeHXc
But actually, my problem is that I can't pass params into the url like https://localhost:8080/user/random_id_here.
With this system, I think the best idea is to find a way to pass params on separated files too, but I don't know how can it be done...
Here's an example of one of my separated file:
module.exports = class NameAPI {
constructor(client) {
this.client = client
}
async run(req, res) {
// Code here
}
}
Maybe you'll have a better system, or a solution for this. Thanks.
You can get the optional params from the module object you already have so each module specifies its own params. This example below shows just adding new params on after the module name, but you could extend this feature to be richer if you needed to.
In a simple implementation, in your loader, you can change this:
posts.forEach((post) => {
const module = new (require(`./routes/post/${post}`))(this);
this.api.post(`/${post}`, async (req, res) => await module.run(req, res))
})
to this:
posts.forEach((post) => {
const module = new (require(`./routes/post/${post}`))(this);
const urlParams = module.params || "";
this.api.post(`/${post}${urlParams}`, async (req, res) => module.run(req, res))
});
So, if a given route wanted the extra URL param /:id added to it, then it would just define the .urlParams property on its exported module object to be `"/:id" and that would be automatically included in the route definition.
P.S. Most of the code in each of the branches of your switch statement in _loadHttpMethode() is identical. With a little factoring into a common function and one or two parameters passed to that function, you can eliminate all the copied code among those different branches of the switch so all each switch does is call one function and pass it a few arguments.
I generally would setup my express to handle this way in that case you want a dynamic insert. This is personal code so do make the adjustments necessary or observe the behavior! :)
WEBAPP.get('/room/:name', (req, res) => {
// Check if URL ends with / (in my case I don't want that)
if (req.url.endsWith('/')) return res.redirect('/');
// Check if URL param "name" matches my regex ex. Username1920 or redirect them
if (req.params.name.match(/^[a-zA-Z0-9]{3,24}$/) === null) return res.redirect('/');
// render the room (sending EJS)
res.render('room', {
title: req.params.name.toUpperCase()
});
});
/*
/*This example accepts one param and must follow my regex/rules*/
So if you were handed /room/test12345 your req.params.name would return a value. Notice the colon to define a param, so you could have /:room/:user/:request and it'd return:
req.params.room, req.params.user, req.params.request all defined! :)
How to seperate routes and parse request parameter in express API
You can just put all your different API methods for each model in a seperated folder, and then just parse the API routes in your main file.
Let's say we have one main file called app.js, and you can organize your API routes/endpoints in subfolders.
folder structure:
├── app.js
└── routes
└── api
└── users.js
users.js in the folder routes/api in this case contains all operations for your users endpoint, and you import this in your app.js file.
Based on the route examples defined below, this will let you parse your express API with these endpoints:
GET YOUR_API:PORT/users // fetch all users
GET YOUR_API:PORT/users/:userId // fetch single user by id
app.js
// this is just a demo app.js, please adapt to your needs
const express = require("express");
// express app
const app = express();
app.use(express.json());
// api routes
// endpoint No. 1, this will create the endpoint /users
// and will enable you to use all methods defined in file users.js
app.use("/users", require("./routes/api/users"));
// add more endpoints, example endpoint No. 2
app.use("/ENDPOINT_NAME", require("./routes/api/FILE_NAME"));
// handle everything else you need to handle in your main file
// run server
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
in subfolder routes/api you add your api route files, like so:
routes/api/users.js
const express = require('express');
const router = express.Router();
// here we only GET all users and user by id,
// but you can add any endpoints required for your API.
// get all users
router.get('/', async (req, res) => {
try {
// do something to get all users
const allUsers = // fetch all users, depends on how you want to do it
return res.status(200).json(allUsers)
} catch (err) {
console.log(err)
return res.status(400).json({ msg: 'Bad request.' })
}
})
// get a specific user by Id from request parameters
router.get('/:userId', async (req, res) => {
try {
// user id from params
const userId = req.params.userId
// do something with this userId, for example look up in DB
return res.status(200).json({userId: `Requested userId is ${userId}`})
)
} catch (err) {
console.log(err)
return res.status(400).json({ msg: 'Bad request.' })
}
})
// add more user endpoints here
// with router.post, router.put, router.delete, whatever you need to do
module.exports = router

How does module.exports = mongoose; work when requiring "./database"?

I'm a MERN stack beginner. I came across this snippet of code from a basic CRUD and I know that it works, but I don't get how.
//in server.js
const database = require('./database');
//in database.js
const mongoose = require('mongoose'); //importing mongoose
mongoose.connect('mongodb://localhost/monguse', {useNewUrlParser:true}) //connected to db
.then((db)=>{console.log('Database connected')}) //message if ok
.catch((err) =>{console.log(`Database connection error: ${err}`)}); //catching errors
module.exports = mongoose;
I understand what is going on in database.js (It is my own version), but why does it work without using any method in server.js? It appears to make the connection only from using the "require" function. then in my routes there is no mention of that again; just using mongoose models in the requests.
Thanks!
In database.js you create an instance of the database and export it by name mongoose, and in server.js you are importing that instance of the mongoDB by name database.

Failing gracefully if any json data is missing in Node.JS post request

I am trying to set up a post request on a node.js server such that if any data from the json report is missing it just throws an error rather than doing anything with the database.
My server is a mongodb server using express and body-parser.
Here is the code I want to create
app.post('/update', function(req, res) {
const params = req.body;
const newData = {
id: params.id,
data: params.data
.../a ton more data
};
if (anything is missing from newData (any field is undefined) ) {
res.send({err: true});
} else {
//Some cool database things
}
}
I realize that I could just check if any of my fields are undefined however that is not really elegant especially when I am about to have about 20 fields in the incoming data.
You can create a JSON schema for your request and then validate your actual request with the existing JSON schema using npm package like ajv
You can checkout more about JSON schema from here. You can create your own JSON schema from here.
there is a module in node JS called JOI which does the initial payload validation.
And for using this with express JS check express-joi
Express Joi Link
var express = require('express');
var expressJoi = require('express-joi');
var Joi = expressJoi.Joi; // The exposed Joi object used to create schemas and custom types
var app = express();
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(app.router);
app.use(errorHandler);
// Use the Joi object to create a few schemas for your routes.
var getUsersSchema = {
limit: expressJoi.Joi.types.Number().integer().min(1).max(25),
offset: expressJoi.Joi.types.Number().integer().min(0).max(25),
name: expressJoi.Joi.types.String().alphanum().min(2).max(25)
};
var updateUserSchema = {
userId: Joi.types.String().alphanum().min(10).max(20),
name: Joi.types.String().min(3).max(50)
};
// Attach the validator to the route definitions
app.get('/users', expressJoi.joiValidate(getUsersSchema), handleUsers);
app.put('/users/:userId', expressJoi.joiValidate(updateUserSchema),
handleUpdateUser);
app.listen(8080);

Categories