i was following some react/express tutorials.
im confused with code below in contacts.js file
if (!contact) {
return res.status(404).json({ msg: "Contact not found" })
}
Is above code necessary ? or whats is there better way to catch if the contact doesn't exist in mongodb ?
when i do put request from postman with invalid id for example
localhost:44022/api/contacts/<invalid ID>
the execution never reach if (!contact) part. if i console log the catch(err) section i get something below
CastError: Cast to ObjectId failed for value "bcvbxcxc" at path "_id" for model "contact"
at model.Query.exec (/Users/becker/Desktop/RJS/ckeeper/node_modules/mongoose/lib/query.js:4380:21)
at model.Query.Query.then (/Users/becker/Desktop/RJS/ckeeper/node_modules/mongoose/lib/query.js:4472:15)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
messageFormat: undefined,
stringValue: '"bcvbxcxc"',
kind: 'ObjectId',
value: 'bcvbxcxc',
path: '_id',
reason: Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
at new ObjectID (/Users/becker/Desktop/RJS/ckeeper/node_modules/bson/lib/bson/objectid.js:59:11)
contacts.js
router.put('/:id', auth, async (req, res) => {
const { name, email, phone, type } = req.body;
const contactFields = {};
if (name) contactFields.name = name;
if (email) contactFields.email = email;
if (phone) contactFields.phone = phone
if (type) contactFields.type = type;
try {
let contact = await Contact.findById(req.params.id);
if (!contact) {
return res.status(404).json({ msg: "Contact not found" })
}
//makesure contact belongs to right user
if (contact.user.toString() != req.user.id) {
return res.status(401).json({ msg: 'Not authorized' })
}
contact = await Contact.findByIdAndUpdate(req.params.id, { $set: contactFields }, { new: true })
res.json(contact)
}
catch (err) {
console.log("reached error, contact not found")
console.error(err)
res.status(500).send(err)
}
});
Contacts.js model
const mongoose = require('mongoose');
const ContactSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'users'
},
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
},
phone: {
type: String
},
type: {
type: String,
default: 'personal'
},
date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('contact', ContactSchema)
The reason for not executing the if(!contact) condition upon exception is because catch block will be called and further execution in the try block is halted. You should rather wrap each db call in its own try catch block. Something like:
let contact;
try {
contact = await Contact.findById(req.params.id);
} catch(err) {
console.log('Some db operations failed due to reason', err);
return res.status(500).json({ msg: "DB operations failed or whatever message" })
}
if (!contact) {
return res.status(404).json({ msg: "Contact not found" })
}
//makesure contact belongs to right user
if (contact.user.toString() != req.user.id) {
return res.status(401).json({ msg: 'Not authorized' })
}
try {
contact = await Contact.findByIdAndUpdate(req.params.id, { $set: contactFields }, { new: true })
return res.json(contact)
}
catch (err) {
console.log("db update operations failed")
console.error(err)
res.status(500).send(err)
}
Related
hope you spent really good holidays
I'm following a tutorial online but i've an error that the teacher doesn't have in the video (i also copy his code but same error).
I have this error only with the "PUT" function but the strange thing is that it updates well in mongoDB. It just gives me an error.
Here's my code:
user.controller.js
const UserModel = require("../models/user.model");
const ObjectID = require("mongoose").Types.ObjectId;
module.exports.getAllUsers = async (req, res) => {
const users = await UserModel.find().select("-password");
res.status(200).json(users);
};
module.exports.userInfo = (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
UserModel.findById(req.params.id, (err, docs) => {
if (!err) res.send(docs);
else console.log("Id unknown" + err);
}).select("-password");
};
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true },
(err, docs) => {
if (!err) return res.send(docs);
if (err) return res.status(500).send({ message: err });
}
);
} catch (err) {
return res.status(500).json({ message: err });
}
};
module.exports.deleteUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
try {
await UserModel.remove({ _id: req.params.id }).exec();
res.status(200).json({ message: "Successfully deleted. " });
} catch (err) {
return res.status(500).json({ message: err });
}
};
user.model.js :
const mongoose = require("mongoose");
const { isEmail } = require("validator");
const bcrypt = require("bcrypt");
const userSchema = new mongoose.Schema(
{
pseudo: {
type: String,
required: true,
minlength: 3,
maxlength: 55,
unique: true,
trim: true,
},
email: {
type: String,
required: true,
validate: [isEmail],
lowercase: true,
trim: true,
},
password: {
type: String,
required: true,
max: 1024,
minlength: 6,
},
picture: {
type: String,
default: "./upload/profil/random-user.png",
},
bio: {
type: String,
max: 1024,
},
followers: {
type: [String],
},
following: {
type: [String],
},
likes: {
type: [String],
},
},
{
timestamps: true,
}
);
// playfunction before save into db
userSchema.pre("save", async function (next) {
const salt = await bcrypt.genSalt();
this.password = await bcrypt.hash(this.password, salt);
next();
});
// Export user
const UserModel = mongoose.model("user", userSchema);
module.exports = UserModel;
Here the error in terminal:
(node:16752) [MONGODB DRIVER] Warning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead. (Use `node --trace-warnings ...` to show where the warning was created) events.js:292
throw er; // Unhandled 'error' event
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:558:11)
at ServerResponse.header (D:\Programmation\mern\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (D:\Programmation\mern\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (D:\Programmation\mern\node_modules\express\lib\response.js:267:15)
at ServerResponse.send (D:\Programmation\mern\node_modules\express\lib\response.js:158:21)
at D:\Programmation\mern\controllers\user.controller.js:33:30
at D:\Programmation\mern\node_modules\mongoose\lib\model.js:4912:18
at processTicksAndRejections (internal/process/task_queues.js:75:11) Emitted 'error' event on Function instance at:
at D:\Programmation\mern\node_modules\mongoose\lib\model.js:4914:15
at processTicksAndRejections (internal/process/task_queues.js:75:11) { code: 'ERR_HTTP_HEADERS_SENT' }
And here the error in PostMan:
(for information, if i put a wrong id in postman i've my error as expected "ID unknown:" ...)
{
"message": {
"originalStack": "Error\n at model.Query._wrappedThunk [as _findOneAndUpdate] (D:\\Programmation\\mern\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:25:28)\n at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:279:20\n at _next (D:\\Programmation\\mern\\node_modules\\kareem\\index.js:103:16)\n at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:508:38\n at processTicksAndRejections (internal/process/task_queues.js:75:11)"
}
}
Earlier i change :
catch (err) {
return res.status(500).json({ message: err });
}"
to a simple
console.log(err)
And had this error in the terminal(but not in Postman anymore):
MongooseError: Query was already executed: user.findOneAndUpdate({ _id: new ObjectId("61363178c0b345e93...
at model.Query._wrappedThunk [as _findOneAndUpdate] (D:\Programmation\mern\node_modules\mongoose\lib\helpers\query\wrapThunk.js:21:19)
at D:\Programmation\mern\node_modules\kareem\index.js:279:20
at _next (D:\Programmation\mern\node_modules\kareem\index.js:103:16)
at D:\Programmation\mern\node_modules\kareem\index.js:508:38
at processTicksAndRejections (internal/process/task_queues.js:75:11) {
originalStack: 'Error\n' +
' at model.Query._wrappedThunk [as _findOneAndUpdate] (D:\\Programmation\\mern\\node_modules\\mongoose\\lib\\helpers\\query\\wrapThunk.js:25:28)\n' +
' at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:279:20\n' +
' at _next (D:\\Programmation\\mern\\node_modules\\kareem\\index.js:103:16)\n' +
' at D:\\Programmation\\mern\\node_modules\\kareem\\index.js:508:38\n' +
' at processTicksAndRejections (internal/process/task_queues.js:75:11)'
}
Thank you in advance for your help !
Have a good day :)
EDIT: After the 1st answer from mohammad Naimi:
I add else, and i still have the same issue, mongodb is actually update but i've the error message
here's my updated code
const UserModel = require("../models/user.model");
const ObjectID = require("mongoose").Types.ObjectId;
module.exports.getAllUsers = async (req, res) => {
const users = await UserModel.find().select("-password");
res.status(200).json(users);
};
module.exports.userInfo = (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
else {
UserModel.findById(req.params.id, (error, docs) => {
if (!error) res.send(docs);
else console.log("Id unknown" + error);
}).select("-password");
}
};
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
else {
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true },
(error, docs) => {
if (!error) return res.send(docs);
else {
return res.status(500).send({ message: error });
}
}
);
} catch (error) {
return res.status(500).json({ message: error });
}
}
};
module.exports.deleteUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
else {
try {
await UserModel.remove({ _id: req.params.id }).exec();
res.status(200).json({ message: "Successfully deleted. " });
} catch (error) {
return res.status(500).json({ message: error });
}
}
};
1st solution: Downgrade your Mongoose version (to 5.10.13 for exemple)
2nd solution: Don't use the callback function, use a .then instead (with Mongoose 6.0.13) :
module.exports.updateUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID invalid : " + req.params.id);
try {
await UserModel.findOneAndUpdate(
{ _id: req.params.id },
{
$set: {
bio: req.body.bio,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true }
)
.then((docs) => res.send(docs))
.catch((err) => res.status(500).send({ message: err }));
} catch (err) {
res.status(500).json({ message: err });
}
};
Ok, so after multiple try and fails ! here's the answer : Use mongoose#5.10.6 and it should be good
Have an awesome day coder buddies
I also experienced the same problem but what I erased the callback functions and instead I used the (then) instead of the callback functions
exports.likePost = async (req, res) => {
if (!objectID.isValid(req.params.id))
return res.status(400).send("ID unkonwn:" + req.params.id);
try {
// update for collection post
await postModel.findByIdAndUpdate(
req.params.id,
{
$addToSet: { likers: req.body.id }
},
{ new: true }
// update for colletcion users
).then(async (resp) => {
await userModel.findOneAndUpdate(
req.body.id,
{ $addToSet: { likes: req.params.id } },
{ new: true }
).then(data => {
return res.status(201).json({ message: 'inserted with success' })
});
});
} catch (error) {
return res.status(400).send(error)
}
}
Ok, so after multiple try and fails ! here's the answer : Use mongoose#5.10.6 and it should be good
Have an awesome day coder buddies
Use "mongoose#5.10.6" and your programm will work
I also had the same error but after several searches, I found that instead of a callback function you have to use
.then((docs) => res.send(docs))
Hello this is the first time I post a question.
So basically i'm build an API to manage car(Im doing this as a training for better building API). My connection to the D is made using a singleton which is called once by server and the mongo promises are global(and it works fine for now)
I have my model:
import mongoose, {Schema} from "mongoose";
import mongooseUniqueValidator from "mongoose-unique-validator";
class Voiture{
initSchema(){
const schema = new Schema({
Marque:{
type: String,
require:true,
},
Modele:{
type: String,
require:true,
},
Année:{
type: Number,
require:true,
},
Energie:{
type: String,
require:true,
},
Boite_De_Vitesse:{
type: String,
require:true,
},
couleur_exterieure:{
type: String,
require:true,
},
couleur_intérieur:{
type: String,
},
nombre_De_Portes:{
type: Number,
},
nombre_De_Places:{
type: Number,
},
Prix:{
type: Number,
},
Etat:{
type: String,
require: true,
},
Kilométrage:{
type: Number,
},
prix_location:{
type: Number,
require:true,
}
},{timestamp: true});
schema.plugin(mongooseUniqueValidator);
mongoose.model("voitures", schema);
}
getInstance() {
this.initSchema();
return mongoose.model("voitures");
}
}
export default Voiture;
and I also have services and controllers attached to them
I can get all the documents in the mongoDB Database but I can't create Documents
Here is my service
import voiture from "../models/Voiture"
import mongoose from "mongoose"
class VoitureService{
constructor(){
this.model = new voiture().getInstance();
this.getAll = this.getAll.bind(this);
this.insert = this.insert.bind(this);
}
/**
* GET All voiture
*/
async getAll(query){
let {skip, limit} = query;
skip = skip ? Number : 0;
limit = limit ? Number : 10;
delete query.skip;
delete query.limit;
if(query._id){
try {
query._id = new mongoose.mongo.ObjetId(uery._id);
} catch (error) {
console.log("not able to generate mongoose id with content", query._id);
}
}
try {
let items = await this.model
.find(query)
.skip(skip)
.limit(limit)
let total = await this.model.countDocuments();
return {
error: false,
statusCode: 200,
data: items,
total
};
} catch (errors) {
return {
error: true,
statusCode: 500,
errors
};
}
}
/**
* Insert a car in the Database
*/
async insert(data){
console.log("line 60");
try {
console.log("line 62");
let item = await this.model.create(data, function (err) {
console.log("line 64");
if (err) return handleError(err);
// saved!
console.log("line 67");
});
if (item){
console.log("line 70");
return {
error: false,
item
};
}
} catch (error) {
console.log("error", error);
return {
error: true,
statusCode: 500,
message: error.message || "Not able to create item",
errors: error.errors
};
}
}
}
And this my controller
async addCar(req, res){
let response = await this.service.insert(req.body)
if (res.error) return res.status(res.statusCode).send(response);
return res.status(201).send(response);
}
I tried to log the Item but it gives me undefined
Thanks to all of you !
Salayna
You can Follow this code
// At Frist, You import **Voiture** Model Then use the model
async insert(data){
console.log("line 60");
try {
console.log("line 62");
let item = await Voiture.create(data, function (err) {
console.log("line 64");
if (err) return handleError(err);
// saved!
console.log("line 67");
});
if (item){
console.log("line 70");
return {
error: false,
item
};
}
} catch (error) {
console.log("error", error);
return {
error: true,
statusCode: 500,
message: error.message || "Not able to create item",
errors: error.errors
};
}
}
I have the following schema with required validations:
var mongoose = require("mongoose");
var validator = require("validator");
var userSchema = new mongoose.Schema(
{
email: {
type: String,
required: [true, "Email is a required field"],
trim: true,
lowercase: true,
unique: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error("Please enter a valid E-mail!");
}
},
},
password: {
type: String,
required: [true, "Password is a required field"],
validate(value) {
if (!validator.isLength(value, { min: 6, max: 1000 })) {
throw Error("Length of the password should be between 6-1000");
}
if (value.toLowerCase().includes("password")) {
throw Error(
'The password should not contain the keyword "password"!'
);
}
},
},
},
{
timestamps: true,
}
);
var User = mongoose.model('User', userSchema);
I pass the email and password through a form by sending post request using the following route:
router.post("/user", async (req, res) => {
try {
var user = new User(req.body);
await user.save();
res.status(200).send(user);
} catch (error) {
res.status(400).send(error);
}
});
module.exports = mongoose.model("User", user);
Whenever I enter a field against the validation rules, I get a very long error message, which is obvious. But now, I want to improve the error handling so that it gets easy to interpret for the users. Rather than redirecting to a generic error page, how can I redirect to the same signup page and display the flash messages near the incorrect fields telling about the error? And also on success, something similar should be done, like a green flash message on the top.
I am using ejs for my signup pages.
In the catch block, you can check if the error is a mongoose validation error, and dynamically create an error object like this:
router.post("/user", async (req, res) => {
try {
var user = new User(req.body);
await user.save();
res.status(200).send(user);
} catch (error) {
if (error.name === "ValidationError") {
let errors = {};
Object.keys(error.errors).forEach((key) => {
errors[key] = error.errors[key].message;
});
return res.status(400).send(errors);
}
res.status(500).send("Something went wrong");
}
});
When we send a request body like this:
{
"email": "test",
"password": "abc"
}
Response will be:
{
"email": "Please enter a valid E-mail!",
"password": "Length of the password should be between 6-1000"
}
you can use validator like this instead of throwing an error :
password:{
type:String,
required:[true, "Password is a required field"],
validate: {
validator: validator.isLength(value,{min:6,max:1000}),
message: "Length of the password should be between 6-1000"
}
}
you can send
res.status(400).send(error.message);
instead of :
res.status(400).send(error);
and you should make some changes in Schema also.
validate(value){
if (!validator.isEmail(value)) {
throw new Error("Please enter a valid E-mail!");
}
}
with
validate: [validator.isEmail, "Please enter a valid E-mail!" ]
and for password:
minlength: 6,
maxlength:1000,
validate:{
validator: function(el){
return el.toLowerCase() !== "password"
}
message: 'The password should not contain the keyword "password"!'
}
If you are using mongoose then you can catch error easily using this method for signup route, by chaining if and else condition depending on your error methods
try {
} catch (error) {
console.log(error);
if (error.errors) {
if (error.errors.password) {
//if password is less than 6 characters
return res.status(400).json(error.errors.password.message)
}
if (error.errors.email) {
//if email is not in correct format. i'm using validator package
return res.status(400).json(error.errors.email.message)
}
} else {
return res.status(400).json(error.message)
}
}
if found simpler one here..
try { } catch (error) {
console.log(error);
// checking validation
if (error.name === "ValidationError") {
const message = Object.values(error.errors).map(value => value.message);
return res.status(400).json({
error: message
})
}
res.status(400).json(error.message)
}
}
I'm using mongoose Model.findOneAndupdate() to find and update my document and there is a post hook on my model schema for which i'm trying to update another document.
The issue i'm facing is post hook is being triggered twice.
My model:
const mongoose = require('mongoose')
const componentSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
component: {
type: String,
required: true
},
message: {
type: String
},
bodyJson: {
type: mongoose.Schema.Types.Mixed
},
question: {
type: String
}
})
componentSchema.post('findOneAndUpdate', function (result) {
console.log('came here')
})
module.exports = mongoose.model('Component', componentSchema)
In my server log i see that came here logged is twice.
update:
try {
await Component.findOneAndUpdate(query, req.body, { new: true }, function (error, doc) {
if (doc) {
return res.status(200).json({ data: doc })
} else if (error) {
return res.status(400).json({ errors: error.message })
} else res.status(404).json({ errors: 'Not found' })
})
} catch (error) {
logger.error('error while updating order: ' + error)
return res.status(400).json({ errors: error.message })
}
moongoose version i'm using is 5.8.11
You are using both await and callback at the same time. This causes the middleware trigger 2 times. Only one of them must be used.
Use either callback:
Component.findOneAndUpdate(query, req.body, { new: true }, function(
error,
doc
) {
if (err) {
return res.status(400).json({ errors: error.message }); //500 status code may be better
} else {
if (doc) {
return res.status(200).json({ data: doc });
} else {
res.status(404).json({ errors: "Not found" });
}
}
});
Or await:
try {
const doc = await Component.findOneAndUpdate(query, req.body, { new: true });
if (doc) {
return res.status(200).json({ data: doc });
} else {
res.status(404).json({ errors: "Not found" });
}
} catch (error) {
logger.error("error while updating order: " + error);
return res.status(400).json({ errors: error.message });
}
I have a route for creating users in Node/Express. I am getting a weird error about a method on the model not existing.
Here is the model for users:
'use strict';
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
mongoose.Promsie = global.Promise;
const UserSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
email: { type: String, required: true },
firstName: { type: String },
lastName: { type: String },
families: [
{
family_key: { type: String, required: true },
family_name: { type: String }
}
]
});
UserSchema.methods.apiRepr = function() {
return {
id: this._id,
firstName: this.firstName,
lastName: this.lastName,
username: this.username,
email: this.email,
families: this.families
};
};
UserSchema.methods.hashPassword = function(password) {
return bcrypt.hash(password, 10);
}
UserSchema.methods.validatePassword = function(password) {
return bcrypt.compare(password, this.password);
}
const User = mongoose.models.User || mongoose.model('User', UserSchema);
module.exports = { User };
Not particularly complicated. BUT, my the route is having trouble with the "hashPassword" method. When I try to use this route, I get an error that says "TypeError: User.hashPassword is not a function"
Here is the route (the issue is close to the bottom):
router.post('/', jsonParser, (req, res) => {
// checking that required fields are present
const requiredFields = ['username', 'password', 'email'];
const missingField = requiredFields.find(field => !(field in req.body));
if(missingField) {
return res.status(422).json({
code: 422,
reason: 'Validation Error',
message: 'Missing field',
location: missingField
});
}
// checking the format of string fields
const stringFields = ['username', 'password', 'email', 'lastname', 'firstname'];
const nonStringField = stringFields.find(
field => field in req.body && typeof req.body[field] !== 'string'
);
if (nonStringField) {
return res.status(422).json({
code: 422,
reason: 'Validation Error',
message: 'Incorrect field type: expected string',
location: nonStringField
});
}
// checking the trimming on fields
const trimmedFields = ['username', 'password', 'email'];
const nonTrimmedField = trimmedFields.find(
field => req.body[field].trim() !== req.body[field]
);
if (nonTrimmedField) {
return res.status(422).json({
code: 422,
reason: 'Validation Error',
message: 'Cannot start or end with whitespace',
location: nonTrimmedField
});
}
// checking length of fields with required length
const sizedFields = {
username: { min: 1 },
password: { min: 10, max: 72 }
};
const tooSmallField = Object.keys(sizedFields).find(field =>
'min' in sizedFields[field] &&
req.body[field].trim().length < sizedFields[field].min
);
const tooLargeField = Object.keys(sizedFields).find(field =>
'max' in sizedFields[field] &&
req.body[field].trim().length > sizedFields[field].max
);
if (tooSmallField || tooLargeField) {
return res.status(422).json({
code: 422,
reason: 'Validation Error',
message: tooSmallField
? `Must be at least ${sizedFields[tooSmallField].min} characters long`
: `Must be at most ${sizedFields[tooLargeField].max} characters long`,
location: tooSmallField || tooLargeField
});
}
// creating the user
let { username, firstname, lastname, families, email, password } = req.body;
return User.find({ username })
.count()
.then(count => {
if(count > 0) {
return Promise.reject({
code: 422,
reason: 'Validation Error',
message: 'Username already taken',
location: 'username'
});
}
return User.hashPassword(password);
})
.then(hash => {
return User.create({ username, firstname, lastname, families, email, password: hash })
})
.then(user => {
return res.status(201).json(user.apiRepr());
})
.catch(err => {
console.error(err)
res.status(500).json({ code: 500, message: 'Internal server error'})
})
})
It does not like the return User.hashPassword(password) part. Any thoughts about what is causing this? I'm copying from a working app. Not sure what I'm doing wrong here.
The methods in node.js can not be used directly using the SchemaName you need to create an object of the schema name and then use the methods of the schema.
Ex:
var AnimalSchema = new Schema({
name: String
, type: String
});
AnimalSchema.methods.findSimilarType = function findSimilarType (cb) {
return this.model('Animal').find({ type: this.type }, cb);
};
var Animal = mongoose.model('Animal', AnimalSchema);
var dog = new Animal({ name: 'Rover', type: 'dog' });
dog.findSimilarType(function (err, dogs) {
if (err) return ...
dogs.forEach(..);
})
Source: http://mongoosejs.com/docs/2.7.x/docs/methods-statics.html
In your code you are trying to access the methods from the model.
Instantiate the model then use the methods.
If need use like the way you are using in the code try using function instead of methods.
module.exports.funtionName = function(/*function params*/){
//function body here
};