Re-use POST and GET methods in Express - mongodb

I'm building a CMS where I have to do a lot of POST and GET requests to my MongoDB. The problem I am having now is that, the more I work on my CMS, the more POST and GET requests I have to do and eventually a lot of double code I'm having in my application. My question is, can I somehow re-use the POST and GET methods? I am using Express framework, MongoDB and Angular on the Front-End.
Here is an example how my application looks like:
Express:
router.post('/news_blocks', function(req, res, next){
var randomNumber = Math.floor(1000 + Math.random() * 9000);
var news_image = req.files.myImage;
news_image.mv('/home//projects/website/public/uploads/' + 'image_' + randomNumber + '.jpg' , function(err) {
if(err){
console.log(err);
}else{
var data = new news_blocks(postOptions(req, randomNumber));
saveToDB(data,res);
}
});
});
router.post('/research', function(req, res, next){
var randomNumber = Math.floor(1000 + Math.random() * 9000);
var research_image = req.files.myImage;
research_image.mv('/home/projects/website/public/uploads/' + 'image_' + randomNumber + '.jpg' , function(err) {
if(err){
console.log(err);
}else{
var data = new research_blocks(postOptions(req, randomNumber));
saveToDB(data,res);
}
});
});
postOptions = function(req, randomNumber){
var options = {
title: req.body.title,
date: new Date,
message: req.body.message,
image: 'image_' + randomNumber
};
return options;
};
MongoDB model:
file1:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var research_block = new mongoose.Schema({
title: String,
date: String,
message: String,
image: String
}, {collection: 'research'});
module.exports = mongoose.model("research", research_block);
File 2:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var news_block = new mongoose.Schema({
title: String,
date: String,
message: String,
image: String
}, {collection: 'news'});
module.exports = mongoose.model("news", news_block);
As you can see, there is a lot of the same code in the POST methods. But I am not sure how I make this more DRY

Suggestion 1:
Make a controller file for every table. And, write functions in it to do all kind of operations in it. And, while calling a service send type of operation along with it. On basis of type you can call any function you want.
Suggestion 2:
Try using GraphQL

Related

Why this MongooseDB population method doesn't work?

I wanted to create a database for MTG combos, and doing something very simple like this, using Mongoose and MLab: We have two schemas, Combo and Card, and two instances of a Card model associated with an instance of a Combo model. When I try to populate the combos of the cards with the name of such combo, it doesn't work and it still shows the ID instead of the name.
var mongoose = require('mongoose') ;
mongoose.connect('mongodb://wernerbusch:xxxx!h#ds115340.mlab.com:15340/wernercito');
var Schema = mongoose.Schema;
var comboSchema = new Schema({
name : String,
cards : [{type: Schema.Types.ObjectId, ref:'Card'}],
type : ["infinite mana", "infinite damage", "draw library", "lethal damage", "storm", "graveyard"]
});
var cardSchema = new Schema({
name: String,
colour:["U","R","B","W","G","C"],
combos: [{type:Schema.Types.ObjectId, ref: 'Combo'}]
})
var Combo = mongoose.model("Combo",comboSchema);
var Card = mongoose.model("Card",cardSchema);
var PanderBurst = new Combo({
name:"PanderBurst",
type:'lethal damage'
})
PanderBurst.save(function(err){
if (err) console.log( err)
var SaprolingBurst = new Card({
name: "Saproling Burst",
colour:["G", "R"],
combos : PanderBurst._id
})
var Pandemonium = new Card({
name: "Pandemonium",
colour:["R"],
combos: PanderBurst._id
})
SaprolingBurst.save(function(err){
if (err) console.log( err)
});
Pandemonium.save(function(err){
if (err) console.log( err)
})
});
Card.find().populate('combos', 'name').exec(function(err,cards){
if (err) console.log (err);
})
After this code is executed, nothing changes in the cards documents.
Have you tried:
Card.find().populate({path: "comboes", select: "name"})
.exec((err,cards)=>{
if (err) console.log (err);
console.log(cards);
});
Using an object has always worked for me.
Update:
you also have:
comboes: {type:Schema.Types.ObjectId, ref: 'Combo'}
in your schema
and combos in your populate.
Final Update:
Populate is used when you make a query. Populating a schema during create isn't good practice because it causes duplication, so call populate with each query.

Access control is not enabled for the database

I am creating an sample library app in nodejs+express+mongodb. when I run the gulp serve command the server start perfectly. when I goto specific mongodb page then it giving error insertMany is not a function.
var express = require('express');
var adminRouter = express.Router();
var mongodb = require('mongodb').MongoClient;
var books = [
{
title: 'world',
genre: 'Lorem Ipsum text changing occured',
author: 'Rakesh',
read: false
},
{
title: 'Make of the world',
genre: 'Digital India towards occured',
author: 'Jumanji',
read: false
}
];
var router = function (nav) {
adminRouter.route('/addBooks')
.get(function (req, res) {
var url = 'mongodb://127.0.0.1:27017/admin';
mongodb.connect(url, function (err, db) {
var collections = db.collections('books');
collections.insertMany(books,
function (err, results) {
res.send(results);
db.close();
}
);
});
});
return adminRouter;
};
module.exports = router;
Mongo cmd screenshots
insertMany cmd not working
There is a typo in syntax in line var collections = db.collections('books');. The node mongo driver could only interpret a db.collection() function not db.collections() which actually is syntactically wrong.
Use db.collection('books') instead of db.collections('books'), this should fix the bug. Try it and let me know

Mongoose Schema hasn't been registered for model when populating

I am trying to join 2 collections using the populate method, I have 3 models artists, albums and songs. My mongodb connection is made on server.js.
my artist model is :
var mongoose = require('mongoose');
//var Album = mongoose.model('Album').schema;
console.log(Album);
var artistsSchema = mongoose.Schema({
name:{
type:String,
required:true
},
albums:{
type:[{type:mongoose.Schema.Types.ObjectId,ref :'Album'}]
}
});
var Artist = mongoose.model('Artist',artistsSchema);
module.exports.getArtistsFull = function(callback,limit)
{
Artist.find().limit(1)
.populate({
path:'albums'
,populate :{path:'albums'}
}).exec(callback);
}
And my albums model:
var mongoose = require('mongoose');
var albumsSchema = mongoose.Schema({
name:{
type:String,
required:true
},
songs:{
type:[{type:mongoose.Schema.Types.ObjectId,ref :'Song'}]
}
});
var Album = mongoose.model('Albums',albumsSchema);
module.exports.getAlbumsWithSongs = function(id,callback,limit){
Album.findById(id)
.populate({
path : 'songs',
populate :{path:'songs'}
}).exec(callback);
}
Whenever I call Artist.getArtistsFull function I get an error"Schema hasn't been registered for model Album", I used console.log(Album) on my Album variable inside artist model and I got the functions that were written there, but I don't have access to albumsSchema.
The problem was actually a simple typo
var Album = mongoose.model('Albums',albumsSchema);
changed to
var Album = mongoose.model('Album',albumsSchema);

inserting in mongo using express

i am trying to put data in the mongodb using express but it is storing blank always ...also it is not printing any console logs :
the url i am hitting after starting the sever is
http://localhost:3000/posts?title=test&link=http://test.com
and it is showing the below output:
{"__v":0,"_id":"562717b064002b1c2e697b33","comments":[],"upvotes":0}
router.get('/posts', function(req, res, next) {
console.log('reached ere '+req);
var post = new Post(req.body);
post.save(function(err, post){
if(err){ return next(err); }
res.json(post);
});
});
Post Scheme:
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: {type: Number, default: 0},
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);
You are calling your API as
http://localhost:3000/posts?title=test&link=http://test.com
which will send title and link to server as query parameters and not body parameters. So your req.body in this case would be an empty object. That is the reason no data in being saved in your posts collection.
You have two options here:
Change your API to save req.query in posts collection which you can do as follows:
Replace
var post = new Post(req.body);
with
var post = new Post(req.query);
Pass link and title as body parameters instead of query parameters.

Mongoose.js instance.save() callback not firing

var mongo = require('mongoose');
var connection = mongo.createConnection('mongodb://127.0.0.1/test');
connection.on("error", function(errorObject){
console.log(errorObject);
console.log('ONERROR');
});
var Schema = mongo.Schema;
var BookSchema = new Schema({ title : {type : String, index : {unique : true}}});
var BookModel = mongo.model('abook', BookSchema);
var b = new BookModel({title : 'aaaaaa'});
b.save( function(e){
if(e){
console.log('error')
}else{
console.log('no error')
}});
Neither the 'error', or 'no error' are printed to the terminal. What's more the connection.on 'error' doesn't seem to fire either. I have confirmed that MongoDb is running.
this is a case where you are adding the model to the global mongoose object but opening a separate connection mongo.createConnection() that the models are not part of. Since the model has no connection it cannot save to the db.
this is solved either by connecting to mongo on the global mongoose connection:
var connection = mongo.createConnection('mongodb://127.0.0.1/test');
// becomes
var connection = mongo.connect('mongodb://127.0.0.1/test');
or by adding your models to your separate connection:
var BookModel = mongo.model('abook', BookSchema);
// becomes
var BookModel = connection.model('abook', BookSchema);
I really like Aaron's answer, and thanks to him I am now on my way to fixing the issue... although I'm not there yet! Here is my particular issue:
I want to have my schema and models defined in separate files, so I can reuse them from project to project. So as an example I have a file named W8DBItem.js as follows:
var mongoose = require('mongoose');
var itemSchema = new mongoose.Schema({ name: {type: String, required: true}});
module.exports = mongoose.model('W8DBItem', itemSchema);
In my program file I do this this:
var mongoose = require('mongoose');
var W8DBItem = require('../w8/W8DBItem.js');
var dbURL ='mongodb://localhost:27017/default';
var mongoOptions = { useNewUrlParser: true, bufferCommands: false }
mongoose.connect(dbURL, mongoOptions);
var db = mongoose.connection;
// DEAL WITH CONNECTION ERROR
db.on('error', console.error.bind(console, 'connection error:'));
// PREP DATA
var aWeight = { name: "My Test Name" };
var newWeightItem = W8DBItem(aWeight);
// CONNECTION ESTABLISHED
db.once('open', function() {
console.log("Here 1")
// TRY TO SAVE
newWeightItem.save(function (err, newWeightItem) {
if (err) {
console.log("Here 2");
console.log(err);
}
else {
console.log("Here 3");
console.log(newWeightItem);
}
});
});
When I run this program I get "Here 1" but never "Here 2" or "Here 3" in the console.
From Aaron's post I get that the W8DBItem object has no associated (and open) connections, but I am not sure how to go about fixing things. I could connect to the DB in the W8DBItem.js file, but I really don't like hard-coding the server info with the objects - I want these objects to be used in different files, and perhaps with different servers.
Ideas and suggestions are much appreciated!
[EDIT: SOLUTION FOUND!!!]
Instead of exporting my mongoose.model from my object file, I am only exporting the schema:
var mongoose = require('mongoose');
var itemSchema = new mongoose.Schema({name: {type: String, required: true}});
module.exports = itemSchema;
In my program files I then do this:
var itemSchema = require('../w8/W8DBItemSchema.js');
...
var W8DBItem = db.model('W8DBItem', itemSchema);
var newWeightItem = W8DBItem(aWeight);
...
Works like a charm. I hope this helps someone!
The posted answer does not solve the problem. Unfortunately, I cannot just upgrade my database, so that is not a solution either for me. But here I found a solution to this problem: https://github.com/Automattic/mongoose/issues/4064
Just use .$__save instead of .save as shown:
var b = new BookModel({title : 'aaaaaa'});
b.$__save({}, function(e){
if(e){
console.log('error')
// callback will show if e exists
}else{
console.log('no error')
// callback will show 'no error'
}});