i am using mongoose to create two models:
but when i try to create a new company and check if it already exist, it gives me an error say exists() is not a working function. Can someone help me out with this as i am new to mongoDB
var mongoose = require('mongoose');
var companySchema = mongoose.Schema({
id: mongoose.Schema.Types.ObjectId,
name:{
type: String,
required: true
}
});
module.exports = mongoose.model('Company', companySchema);
const mongoose = require('mongoose');
let shopSchema = mongoose.Schema({
name: {
type: String,
required: true
},
address: {
type: String,
required: true
},
company: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Company'
},
date: {
type: Date,
default: Date.now
},
brandingDetails: {
type: String,
required: true
},
image: {
data: Buffer,
contentType: String
},
length: {
type: Number,
required: true
},
width: {
type: Number,
required: true
},
height: {
type: Number,
required: true
},
});
module.exports = mongoose.model('Shop', shopSchema);
code for creating a new company:
module.exports.createCompany = (userDetails) => {
return new Promise(function myFn(resolve, reject) {
var companyData = new company();
userDetails.name = userDetails.name.trim();
companyData.exists(
{ name: userDetails.name },
function returnData(error, result) {
if (error) {
reject(false);
} else {
if (result) {
reject(false);
} else {
companyData.name = userDetails.name;
companyData.save(function resultHandle(error, result) {
if (error) {
reject(false);
} else {
resolve(true);
}
});
}
}
}
);
});
};
im getting this error
Error: Route.post() requires a callback function but got a [object Undefined]
at Route.<computed> [as post] (C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\route.js:211:15)
at Object.<anonymous> (C:\Users\ashto\Desktop\FIT2095\App\Backend\routes\routes.js:10:33)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
TypeError: companyData.exists is not a function
at myFn (C:\Users\ashto\Desktop\FIT2095\App\Backend\src\user\userService.js:21:17)
at new Promise (<anonymous>)
at Object.module.exports.createCompany (C:\Users\ashto\Desktop\FIT2095\App\Backend\src\user\userService.js:17:10)
at createCompany (C:\Users\ashto\Desktop\FIT2095\App\Backend\src\user\userController.js:11:36)
at Layer.handle [as handle_request] (C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\route.js:144:13)
at Route.dispatch (C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\route.js:114:3)
at Layer.handle [as handle_request] (C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\index.js:284:15
at Function.process_params (C:\Users\ashto\Desktop\FIT2095\App\Backend\node_modules\express\lib\router\index.js:346:12)
can someone guide me on how to fix it? i dont know what im doing wrong
Try to change your code to:
module.exports.createCompany = (userDetails) => {
return new Promise(function myFn(resolve, reject) {
userDetails.name = userDetails.name.trim();
company.exists({ name: userDetails.name }, (err, result) => {
if (error) {
reject(false);
} else {
if (result) {
reject(false);
} else {
const newCompany = new company();
newCompany.name = userDetails.name;
newCompany.save(function resultHandle(error, result) {
if (error) {
reject(false);
} else {
resolve(true);
}
});
}
}
});
});
};
Related
I’m pretty new to using Mongoose and can’t seem to find a fix. I have two schema’s; postSchema, commentSchema. The first one is for a post and the second is for comments that are stored within the post. Both schema’s have a map field to store likes. The post likes field’s setter and getter work when I try to update but when I try to do the same for the comments it gives me an error that the set or get is not a function. When I check if the likes are an instance of a map, the post likes will return true, while the comments like will return false. If anyone could help or direct me in the right direction it would be greatly appreciated.
Here is the code that I'm working with. When I create a comment to add to a post, the comment.likes checks as a Map. After I update the post I make a call to get all the post's and I rechecked that the comment.likes is a Map, but now it turns out false.
import mongoose from 'mongoose';
const postSchema = mongoose.Schema(
{
userId: {
type: String,
required: true,
},
userName: {
type: String,
required: true,
},
picturePath: {
type: String,
default: '',
},
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
likes: {
type: Map,
of: Boolean,
default: new Map(),
},
comments: {
type: Array,
default: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
},
},
{ timestamps: true }
);
const Post = mongoose.model('Post', postSchema);
export default Post;
import mongoose from 'mongoose';
const commentSchema = mongoose.Schema(
{
postId: {
type: String,
required: true,
},
userId: {
type: String,
required: true,
},
userName: {
type: String,
required: true,
},
picturePath: {
type: String,
default: '',
},
description: {
type: String,
required: true,
},
likes: {
type: Map,
of: Boolean,
default: new Map(),
},
},
{ timestamps: true }
);
const Comment = mongoose.model('Comment', commentSchema);
export default Comment;
export const addComment = async (req, res) => {
try {
const { id } = req.params;
const { userId, picturePath, description } = req.body;
const user = await User.findById(userId);
const newComment = new Comment({
id,
userId,
userName: user.userName,
picturePath,
//likes: {},
description,
});
newComment.set('likes', new Map());
console.log(newComment.likes instanceof Map);
const upDatedPost = await Post.findByIdAndUpdate(
id,
{ $push: { comments: newComment } },
{ new: true }
);
const allPost = await Post.find();
console.log(allPost[0].comments[2].likes instanceof Map);
res.status(200).json(allPost);
} catch (err) {
console.log('err');
res.status(404).json({ message: err.message });
}
};
This works for the post.likes.
export const likePost = async (req, res) => {
try {
const { id } = req.params;
const { userId } = req.body;
const post = await Post.findById(id);
const isLiked = post.likes.get(userId);
if (isLiked) {
post.likes.delete(userId);
} else {
post.likes.set(userId, true);
}
const upDatedPost = await Post.findByIdAndUpdate(
id,
{ likes: post.likes },
{ new: true }
);
res.status(200).json(upDatedPost);
} catch (err) {
res.status(404).json({ message: err.message });
}
};
This doesn’t work. When I check if element.likes is an instanceOf Map it gives back false, but for post.likes it returns true. Updated with the console.log's.
export const likeComment = async (req, res) => {
try {
const { id } = req.params;
const { postId, userId } = req.body;
let post = await Post.findById(postId);
let comments = post.comments;
console.log('comments: ', comments);
console.log('likes: ', comments[0].likes);
console.log(
'Is likes an instanceof Map: ',
post.comments[0].likes instanceof Map
);
//comments[0].likes.set(userId, true);
//post.comments[0].set('likes', new Map());
//console.log(comments[6].likes);
// comments.forEach((element) => {
// if (element._id.toString() === id) {
// element.likes.set(userId, true);
// }
// });
res.status(200).json(post);
} catch (err) {
res.status(404).json({ message: err.message });
}
};
Here is the output fro the console.log's.
comments: [
{
userId: '63dc0274bd8c03b1e417cfc4',
userName: 'dummyUserThree',
picturePath: '',
description: 'Likes still not working',
_id: new ObjectId("63e13f26603a052fc8f16b09"),
likes: {}
}
]
likes: {}
Is likes an instanceof Map: false
I'm using Sequelize with expressjs for my api, I have a model named "Order" for the orders of the website im currently making, this is my model order:
module.exports = (sequelize, Sequelize) => {
const Order = sequelize.define("order", {
uid: {
type: Sequelize.STRING
},
author: {
type: Sequelize.TEXT('long'),
get: function() {
return JSON.parse(this.getDataValue('author'));
},
set: function(author) {
this.setDataValue('author', JSON.stringify(author));
}
},
cart: {
type: Sequelize.TEXT('long'),
get: function() {
return JSON.parse(this.getDataValue('cart'));
},
set: function(cart) {
this.setDataValue('cart', JSON.stringify(cart));
}
},
delivery: {
type: Sequelize.TEXT('long'),
get: function() {
return JSON.parse(this.getDataValue('delivery'));
},
set: function(delivery) {
this.setDataValue('delivery', JSON.stringify(delivery));
}
},
shipmethod: {
type: Sequelize.STRING
},
paymethod: {
type: Sequelize.STRING
},
totalprice: {
type: Sequelize.DECIMAL
},
cryptoprice: {
type: Sequelize.DECIMAL
},
payed: {
type: Sequelize.DECIMAL
},
promoCode: {
type: Sequelize.STRING
},
status: {
type: Sequelize.STRING
}
});
return Order;
}
All was working good, until I try to update an order, like this:
router.post('/payment/crypto', async (req, res) => {
const {order, currency} = req.body;
if (!order, !currency) return res.status(404).json({error: 'not found'});
console.log(order);
console.log(currency);
try {
const orderDb = await db.orders.findOne({where:{uid: order}});
if (!orderDb) return res.status(404).json({error: 'not found'});
const cryptoPrice = await crypto.convertPrice(currency, (parseFloat(orderDb.totalPrice) + 5));
// HERE
await db.orders.update({cryptoprice: cryptoPrice}, { where: {uid: order}});
const wallet = await crypto.generateWallet(currency, '1P5ZEDWTKTFGxQjZphgWPQUpe554WKDfHQ', 'https://google.fr');
return res.status(200).json({address: wallet.address, price: cryptoPrice});
} catch (error) {
console.error(error);
return res.status(404).json({error: error});
}
});
The findOne method works correctly, but when just after I update this order, I got this error:
SyntaxError: "undefined" is not valid JSON
at JSON.parse (<anonymous>)
at model.get (shopapp\back\src\database\models\Order.model.js:9:29)
at model.get (shopapp\back\node_modules\sequelize\lib\model.js:2116:41)
at model.get (shopapp\back\node_modules\sequelize\lib\model.js:2138:33)
at order.update (shopapp\back\node_modules\sequelize\lib\model.js:1877:44)
at shopapp\back\src\routes.js:132:29
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
The line number 9 of my Order.model.js is :
get: function() {
return JSON.parse(this.getDataValue('author'));
},
I dont understand cause the author column is not null, and even with the findOne I can get it
Initially, the project was set up with promise support, and all queries used promise like method.then().catch() later some were converted to try-catch with async await. All worked fine until a few weeks ago when all of a sudden some methods stopped working, I have tried converting the methods to many different variations from promise to callback and to try-catch. await new Model(object).save() does not save the record. I am using mongoose.createConnection because I need to connect to two databases.
Here is how I init my DB
const mongoose = require("mongoose");
mongoose.Promise = require('bluebird');
function makeNewConnection(uri, id) {
const db = mongoose.createConnection(uri);
db.on("error", function(error) {
console.log(
`MongoDB :: connection ${this.name} :: ${id} ${JSON.stringify(error)}`
);
db.close().catch(() =>
console.log(`MongoDB :: failed to close connection ${this.name}`)
);
});
db.on("connected", async function() {
mongoose.set("debug", function(col, method, query, doc) {
console.log(
`MongoDB :: ${
this.conn.name
} :: ${id} ${col}.${method}(${JSON.stringify(query)},${JSON.stringify(
doc
)})`
);
});
console.log(`MongoDB :: connected ${this.name} :: ${id}`);
require("../models/notification.model");
if (process.env.DATABASE_ENV === "local" && id === "cloud") {
require("../helpers/data.sync.helper");
}
});
db.on("disconnected", function() {
console.log(`MongoDB :: disconnected ${this.name} :: ${id}`);
});
return db;
}
// Use
let local, cloud;
if (process.env?.DATABASE_ENV === "local") {
// Connect to local database
local = makeNewConnection(
`mongodb://${process.env.DATABASE_USER}:${process.env.DATABASE_PASS}#127.0.0.1:27017/Eyemasters?retryWrites=true&authSource=admin&useNewUrlParser=true&useUnifiedTopology=true&w=majority`,
"local"
);
// Connect to cloud database
cloud = makeNewConnection(
`mongodb://${process.env.DATABASE_USER}:${process.env.DATABASE_PASS}#64.227.44.132:27017/Eyemasters?retryWrites=true&w=majority`,
"cloud"
);
// Start Database sync helper
} else {
// Connect to cloud local database
local = makeNewConnection(
`mongodb://${process.env.DATABASE_USER}:${process.env.DATABASE_PASS}#localhost:27017/Eyemasters?retryWrites=true&w=majority`,
"local"
);
}
module.exports = {
local,
cloud
};
And here is one of my models having the issue.
const mongoose = require("mongoose");
mongoose.Promise = require('bluebird');
const { local, cloud } = require("../config/database.config");
const { genId } = require("../helpers/doc.id.generator");
const validator = require("validator");
const UserSchema = mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId,
email: {
type: String,
required: true,
unique: true,
validate: {
validator: validator.isEmail,
message: "{VALUE} is not a valid email",
isAsync: false
}
},
hash: { type: String, bcrypt: true, rounds: 10 },
firstname: { type: String, required: true },
lastname: { type: String, required: true },
phone: { type: String },
dateOfBirth: { type: Date },
designation: { type: String },
role: { type: mongoose.Schema.Types.ObjectId, ref: "Role" },
passport: { type: String },
accountDetails: {
name: String,
number: Number,
bank: String
},
defaultBranch: {
type: mongoose.Schema.Types.ObjectId,
ref: "Branch"
},
branches: [{ type: mongoose.Schema.Types.ObjectId, ref: "Branch" }],
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
lastModifiedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
webpush: { type: Object },
inactive: { type: Boolean, default: true },
approved: { type: Boolean, default: false },
activationCode: { type: String, unique: true },
activationExpiresIn: { type: Date }
},
{ toJSON: { virtuals: true }, timestamps: true }
);
UserSchema.plugin(require("mongoose-bcrypt"));
genId(UserSchema);
UserSchema.pre("save", function(next) {
if (!this.createdBy) this.createdBy = this._id;
if (!this.lastModifiedBy) this.lastModifiedBy = this._id;
});
exports.User = exports.User || local.model("User", UserSchema);
exports.OnlineUser = exports.OnlineUser || cloud.model("User", UserSchema);
And Lastly my controller setup;
exports.create = async (req, res) => {
// Validating entered data
if (
!req.body.firstname ||
!req.body.lastname ||
req.body.firstname.length < 3 ||
req.body.lastname.length < 3 ||
!req.body.email ||
!req.body.role ||
req.body.email.length < 3
) {
return res.status(400).send({
message: "Please fill in all required fields"
});
}
try {
const user = await User.findOne({
email: req.body.email.toLowerCase()
});
if (user) {
throw new Error("User with email " + req.body.email + " already exist");
}
console.log("Before create");
let newUser = new User({
...req.body,
activationCode: randtoken.uid(16),
activationExpiresIn: moment.utc().add(30, "minutes"),
email: req.body.email.toLowerCase()
});
console.log(newUser.save);
const userData = await newUser.save();
console.log("Saved");
let transaction = new DbTransaction({
transactionType: "insert",
modelName: "User",
data: userData,
clients: [process.env.DATABASE_CLIENT_ID],
isProcessed: false
});
await transaction
.save()
.then(d => console.log("Transaction updated successfully"))
await User.populate(userData, populateQuery, (err, data) => {
if (err) throw new Error(err);
return res
.status(201)
.send({ message: "User created successfully", user: data });
});
} catch (err) {
console.log(err);
console.log(err.kind);
return res.status(500).send({
message: err.message
});
}
};
I have tried different variants of javascript promise based work flow. Like Model.method().then().catch(), async try-await Model.method()-catch and lastly callback Model.method((err, data)=>{ //do something }).
None of the above conbination has worked. My observation is that mongoose just logs "done" into the console for this method but never action is never actually performed.
Your help is greatly appreciated, I have absolutely no idea why this is not working.
Thank you.
To all who made effort to assist, Thank you for the help.
I don't know why I am seeing the problem after posting here.
The issue was coming from not calling next in the middleware inside the model setup;
UserSchema.pre("save", function(next) {
if (!this.createdBy) this.createdBy = this._id;
if (!this.lastModifiedBy) this.lastModifiedBy = this._id;
});
Replace with;
UserSchema.pre("save", function(next) {
if (!this.createdBy) this.createdBy = this._id;
if (!this.lastModifiedBy) this.lastModifiedBy = this._id;
next();
});
Thank you all once again for your support.
I'm quite new to node and mongoose. I'm trying to do a project using them, but i'm running into an error while trying to populate. The comment is saved to the Comment schema perfectly, but throws an error when i reference it Organization Schema.Please advise me on what i'm doing wrong. Any form of assistance will be appreciated.
// Post route for comment(on the Organization's profile page)
router.post('/comment/:id', ensureAuthenticated,(req, res) =>{
let id = req.params.id;
console.log(mongoose.Types.ObjectId.isValid(id))
const commentObject = new Comment({
sender: 'Fred kimani',
commentBody: req.body.commentBody
})
console.log(commentObject);
commentObject.save((err, result) =>{
if(err){console.log(err)}
else{
Organization.findByIdAndUpdate(id, {$push: {comments: result}}, {upsert: true}, (err, organization) =>{
if(err){console.log(err)}
else{
console.log('======Comments====')
}
})
res.redirect('/users/organizationprofilepage/:id')
}
})
});
//Organization Schema
const mongoose = require('mongoose');
const OrganizationSchema = new mongoose.Schema({
organization_name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
category: {
type: String,
required: true
},
isApproved: {
type: Boolean,
default: false
},
image:{
type:String,
required:true
},
description: {
type: String,
required: true,
},
comments: [{
type: mongoose.Types.ObjectId,
ref: 'Comment'
}],
},
//{ typeKey: '$type' }
);
OrganizationSchema.statics.getOrganizations = async function () {
try {
const organizations = await this.find();
return organizations;
} catch (error) {
throw error;
}
}
//defines the layout of the db schema
const Organization = mongoose.model('0rganization', OrganizationSchema);
module.exports = Organization;
//Comment schema
const mongoose = require('mongoose');
const CommentSchema = mongoose.Schema({
sender: {
type: String,
},
commentBody: {
type: String,
required: false,
},
date: {
type: Date,
default: Date.now
},
})
CommentSchema.statics.getComments= async function () {
try {
const comments = await this.find();
return comments ;
} catch (error) {
throw error;
}
}
const Comment= mongoose.model('Comment', CommentSchema);
module.exports = Comment;
Try to change the comments type to mongoose.Schema.Types.ObjectId:
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
},
],
Try to push the new commend _id into the Organization object after its creation, not the whole object:
commentObject.save((err, result) => {
if (err) {
console.log(err);
} else {
Organization.findByIdAndUpdate(
id,
{ $push: { comments: result._id } }, // <- Change this line
{ upsert: true },
(err, organization) => { }
);
...
}
});
If you just updated the schema you will need to make sure all of the comments are following the new form you created, when you save it will attempt to validate them, that is why an updateOne will work but not await save()
I have route and model for User and then another for Loan. I'm trying to reference the user inside the Loan route but I get this error anytime I test on PostMan:
TypeError: Cannot read property '_id' of undefined
at C:\Users\Micho\Documents\GBENGA\BE\src\routes\loans\index.js:38:47
Loan Model code is:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const loanSchema = new Schema({
customerName: {
type: String,
required: true
},
gender: {
type: String
},
address: {
city: String,
state: String,
},
amount: {
type: Number
},
loanTenure: {
type: Number
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
loanStatus: {
type: String,
default: "created"
}
}, {
timestamps: true
})
My route is this:
router.post("/", async (req, res) => {
try {
let loan = await new Loan({...req.body});
loan.save();
await User.findByIdAndUpdate(req.user._id, { $push: { loans: loan._id } })
console.log(req.user)
loan = await Loan.findById(loan._id).populate("user");
res.send(loan);
} catch (error) {
console.log(error)
res.status(500).send(error);
}
});
Kindly help. Thanks