CALL_NON_FUNCTION_AS_CONSTRUCTOR (native) - node.js

I'm trying to use a new schema in my db, but get errors while trying to instantiate it. I have two other schemas (in two different model files in the folder "models"), that works perfect, and they are shaped in the same way. What does the error message mean and what can I do different to prevent it from occur?
I don't thinks its any problem with the other code in the controller, because i've tried to instantiate another db model in the same place using the same syntax, and that works fine.
The error I get: 500 TypeError: object is not a function
at Schema.CALL_NON_FUNCTION_AS_CONSTRUCTOR (native)
Sorry for all the code below. I didn't know what I could exclude in this case.
Anyway, thanks in advance!
controller file:
module.exports = function(app, service) {
var imageModel = service.useModel('image');
app.post('/file-upload', function(req, res, next) {
// other code...
var imageAdd = new imageModel.ImgSchema();
}
}
mongodb model (models/image.js):
module.exports = function (mongoose) {
var modelObject = {};
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var ImgSchema = new Schema({
name : String,
size : Number,
type : String
});
modelObject.ImgSchema = ImgSchema;
modelObject.Images = mongoose.model('Images', ImgSchema);
return modelObject;
};
For mongodb I'm using a service file (service.js):
var environment;
var mongoose = require('mongoose');
module.exports.init = function(env, mongoose) {
environment = env;
mongoose = mongoose;
};
module.exports.useModel = function (modelName) {
var checkConnectionExists = (mongoose.connection.readyState === 1 || mongoose.connection.readyState === 2);
if(!checkConnectionExists)
mongoose.connect(environment.db.URL);
return require("./models/" + modelName)(mongoose);
};
module.exports.useModule = function (moduleName) {
return require("./modules/" + moduleName);
};

The modelObject.ImgSchema is not a constructor, however, modelObject.Images is.
var imageAdd = new imageModel.Images();
I'd probably rename Images to Image

Related

How to perform bulk upload in mongoose (node.js)

I am trying to perform bulk upload in node js and mongodb is my db,can anyone suggest me some best articles regarding this.Thanks in advance.
You can use Model.collection.insert or Model.insertMany as below where collections is array of items in bulk.
Model.collection.insert(collections, function (err, models) {
next(err, models);
});
OR,
Model.insertMany(collections, function (err, models) {
next(err, models);
});
Mongoose reference: http://mongoosejs.com/docs/api.html#model_Model.insertMany
Mongo reference: https://docs.mongodb.com/v3.2/reference/method/db.collection.insert/
You can insert multiple records with batch/bulk insert in mongoose.
var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }];
Movies.insertMany(arr, function(error, docs) {});
Let's say i have an excel file employees.xlsx with following data and i want perform bulk write.
There are several libraries out there for converting excel data to json in node, i use xlsx but it's personal taste you can use whatever is convenient for you.
Here is a helper i use for reading "/public/employees.xlsx" file.I found the content from here here.
//** helper/excel-reader.js **//
var excelReader = {};
excelReader.readExcel = function(filePath){
var XLSX = require('xlsx');
var workbook = XLSX.readFile(filePath);
var sheet_name_list = workbook.SheetNames;
var data = [];
sheet_name_list.forEach(function(y) {
var worksheet = workbook.Sheets[y];
var headers = {};
for(z in worksheet) {
if(z[0] === '!') continue;
//parse out the column, row, and value
var tt = 0;
for (var i = 0; i < z.length; i++) {
if (!isNaN(z[i])) {
tt = i;
break;
}
};
var col = z.substring(0,tt);
var row = parseInt(z.substring(tt));
var value = worksheet[z].v;
//store header names
if(row == 1 && value) {
headers[col] = value;
continue;
}
if(!data[row]) data[row]={};
data[row][headers[col]] = value;
}
//drop those first two rows which are empty
data.shift();
data.shift();
});
return data;
}
module.exports = excelReader;
Now the employee model somehow looks like this.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var employee = new Schema({
name: String,
adderess: String,
phonenumber: String
});
module.exports = mongoose.model('Employee', employee);
Now let's use the above code so here is my users.js route whenever i type "localhost:3000/users" it write the csv content to database.
var express = require('express');
var router = express.Router();
var excelReader = require('../helpers/excel-reader');
var mongoose = require('mongoose');
var Employee = require('../models/employee');
/* GET users listing. */
router.get('/', function(req, res, next) {
var employeesJsonArray = excelReader.readExcel('./public/employees.xlsx')
Employee.insertMany(employeesJsonArray,function(error, docs) {
if(error){
next(error)
}
else{
res.json(docs);//just rendering the document i got
}
});
});
module.exports = router;
Hope this helps!!

How to save base64 directly to mongoose in express js

I want to save an image not in my server but in my database.
this is my model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var categorySchema = new Schema({
img: { data: Buffer, contentType: String },
});
module.exports = mongoose.model('Category', categorySchema);
now in my router I'm getting this base64 image with a long string.
{ '$ngfDataUrl': 'data:image/png;base64,long-String'}
I want to know how do I save this information in my mongoose db database so far i have this.
router.post('/add', function (req, res) {
var category = new Category();
category.img.data = req.body.category.img;
category.img.contentType = 'image/png';
category.save(function (err) {
if (err) throw new Error(err);
res.sendStatus(200)
});
but obviously that is not working i get this error.
Error: ValidationError: CastError: Cast to Buffer failed for value "{
'$ngfDataUrl': 'data:image/png;base64, long-String'}
Thanks in advance I'm in saving files.
You'll want to actually pull out the base64 string from the request body, and save that.
Is req.body.category.img equal to { '$ngfDataUrl': 'data:image/png;base64,long-String' }, where long-String is the base64 representation of the image?
If so, do something like this:
const category = new Category();
const img = req.body.category.img;
const data = img['$ngfDataUrl'];
const split = data.split(','); // or whatever is appropriate here. this will work for the example given
const base64string = split[1];
const buffer = Buffer.from(base64string, 'base64');
category.img.data = buffer;
// carry on as you have it

Mongoose.create creating document but none of my data

I'm learning to use the mean stack and trying to build a url shortener. I've got a module that takes the req.params.UserUrl checks and makes sure it's a valid url then creates a random number that I want to use as the short route. I can't seem to find a way to save the random number so that I can check their next url request against it. After a google search it seemed maybe the most effecient way would be to save an object in the database with the long_url and the short_url:randomNumber. My code doesn't throw any errors but when I check my heroku database it has a new entry but only has the _id and __v that mLabs generates itself. Can someone tell me where I'm going wrong.
Route File
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var URLShortener = require(process.cwd()+'/public/Modules/urlShortener.module.js');
var ShortURL = require('../models/shortUrl.js');
router.get('/', function(req, res) {
res.render('index', { title: 'FreeCodeCamp Projects' });
});
router.get('/urlShortener', function(req, res){
res.render('freecodecamp/urlShortener', { title: 'Url Shortener Site'});
});
router.get('/urlShortener/:userUrl', function(req, res){
if(URLShortener.checkValidUrl(req.params.userUrl))
{
var UserUrl = req.params.userUrl;
var randNbr = URLShortener.assignRanNbr();
ShortURL.create(URLShortener.createUrlObj(UserUrl, randNbr), function (err, smallUrl) {
if (err) return console.log(err);
else res.json(smallUrl);
});
}
else
{
res.send('Invalid url');
}
});
router.get('/:short', function(req, res){
if(randNbr == req.params.short)
{
res.redirect(userUrl);
}
else
{
res.send('Not the correct shortcut');
}
});
module.exports = router;
Url Schema
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var shortUrlSchema = new Schema({
long_id:String,
short_id:Number
}, {collection: 'shortUrl'});
module.exports = mongoose.model('shortUrl', shortUrlSchema);
urlShortener Module
'use strict'
module.exports.checkValidUrl = function(url){
var pattern = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+#)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+#)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%#.\w_]*)#?(?:[\w]*))?)/);
return pattern.test(url);
}
module.exports.assignRanNbr = function(){
var randNbr = Math.floor(Math.random() * (9999 - 1 + 1)) + 1;
return randNbr;
}
module.exports.createUrlObj = function(url, num){
var urlObj = {};
urlObj.original_url = url;
urlObj.short_url = 'https://rawlejuglal-me-rawlejuglal-1.c9users.io/freecodecamp/'+num;
return urlObj;
}
Your createUrlObj method is returning an object with the properties original_url and short_url, but your shortUrlSchema properties are long_id and short_id. The property names in your create method need to match your schema. The property value types must also match your schema types (currently short_url is a string and short_id is a number). I think what you really want is for your createUrlObj method to be
module.exports.createUrlObj = function(url, num){
var urlObj = {};
urlObj.long_url = url;
urlObj.short_id = num;
return urlObj;
}
and your schema to be
var shortUrlSchema = new mongoose.Schema({
long_url: String,
short_id: Number
}, {collection: 'shortUrl'});
Additionally, your '/:short' route should have a call to the database since the randNbr and userUrl variables are not defined in that route.
router.get('/:short', function(req, res){
ShortUrl.findOne({short_id: req.params.short}, function(err, shortUrl){
if(err) res.send('Invalid Url');
res.redirect(shortUrl.long_url)
})
});

Multiple Databases in Mongoose and NodeJS Using The Same Referenced File Schema

I'm building a web app that I would like to use with two databases based on a GET query. These two databases have the same schema, the only difference is one has live data and the other is scrubbed (or test) data.
This works fine, but I'm wondering if this is the proper way to go about solving this problem.
I'm referencing a model with a schema: names_model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var namesSchema = new Schema({
name: String,
createdAt: String
});
module.exports = mongoose.model('names', namesSchema);
And this is my main file. If the param query is 1 it will connect to the first db, else it will go connect to the second db.
var mongoose = require('mongoose');
var db = mongoose.createConnection('mongodb://localhost/database1');
var db2 = db.useDb('database2');
var NamesDB = require('./names_model.js');
var Connect = db.model('names', NamesDB);
var Connect2 = db2.model('names', NamesDB);
exports.getData = function(dbName, sendBack) {
console.log(dbName);
if (dbName == 1) {
var Names = Connect;
}
else {
Names = Connect2;
}
Names.find({}, function (err, docs) {
if (err) {
console.log(err)
}
else {
sendBack(docs);
}
});
};
Like I mentioned above, this does work, though I feel that I might be making extra steps for myself, but I'm not quite sure. I'm hoping someone might be able to tell me if theres an easier way.
Thanks!
T
You could use an environment variable to define if you are on "live/production" site or the development one.
Define an env variable in your systems, usually it is NODE_ENV=<env-name> and then use a condition on process.env.NODE_ENV to define what to use for each env:
var dbName;
if (process.env.NODE_ENV === 'development') {
// Define the development db
dbName = 'database1';
} else if (process.env.NODE_ENV === 'production') {
// Define the production db
dbName = 'database2';
}
var db = mongoose.createConnection('mongodb://localhost/' + dbName);
var NamesDB = require('./names_model.js');
var Connect = db.model('names', NamesDB);

Trying to use gridfs but something is not outputting correctly

Hey so I am trying to use gridfs to store profile pictures... I am not sure what I am doing wrong, I am kind of new to this as well.
This is what I got so far, but it seems to be erroring this:
TypeError: Cannot read property 'primary' of undefined
at Stream.GridStore.open (..\node_modules\mongodb\lib\mongodb\gridfs\gridstore.js:146:69)
This is my code:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = mongoose.Schema.Types.ObjectId;
var GridStore = require('mongodb').GridStore;
var Step = require('step');
exports.newProfilePicturePost = function(req, res) {
var db = mongoose.createConnection('mongodb://localhost/test5');
var fileId = new ObjectId();
var gridStore = new GridStore(db, fileId, "w", {
"metadata": {
category: 'image'
}, content_type: 'image'});
gridStore.chunkSize = 1024 * 256;
gridStore.open(function(err, gridStore) {
Step(
function writeData() {
var group = this.group();
for(var i = 0; i < 1000000; i += 5000) {
gridStore.write(new Buffer(5000), group());
}
},
function doneWithWrite() {
gridStore.close(function(err, result) {
console.log("File has been written to GridFS");
});
}
)
});
};
Any help or fixes I should make to my code is welcomed, also I am not sure how to specify the collection I want to store the picture in and I want to also add the userId to the picture being saved in the collection for fetching it later.

Resources