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
Related
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()
How can I update data in MongoDB when I check the checkbox without submitting any form.
My Schema
const userSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
},
todos: [
{
task: {
type: String,
trim: true,
required: 'Please Enter your Task',
},
dueDate: {
type: Date,
default: new Date(+new Date() + 3 * 24 * 60 * 60 * 1000),
},
dueTime: String,
done: {
type: Boolean,
default: false,
},
},
],
});
I want to update the done element which is in todos array.
I tried to do this.
Main Client Side JavaScript
$(document).ready(function () {
$('.todo--checkbox').change(function () {
let isChecked;
if (this.checked) {
isChecked = true;
$.ajax({
url: '/todo/' + this.value,
type: 'PUT',
data: { done: true },
});
} else {
isChecked = false;
$.ajax({
url: '/todo/' + this.value,
type: 'PUT',
data: { done: false },
});
}
});
});
In the front-end I have set the value of the checkbox to the _id of the object.
/routes/index.js here I am handling my routes
router.put('/todo/:id', todoControllers.checkStatus);
And Finally I am handling that contorller in my todoCOntroller.js
exports.checkStatus = async (req, res) => {
try {
const user = await User.aggregate([
{ $unwind: '$todos' },
{ $match: { 'todos._id': req.params.id } },
]);
// res.json(user);
console.log(user);
} catch (err) {
console.log('error: ', err);
}
};
But I am not getting any user in my console.
Please tell me where I am wrong.
You don't need to use aggregate. You can do it by using $elemMatch
const user = await User.find({
todos: { $elemMatch: { _id: req.params.id } },
});
For more information read the docs
want to fetch all users but just return list of _ids , checked the saved data in db everything seems good.
this is the user model
let UserSchema = new mongoose.Schema({
firstName: {
type: String,
minlength: 3,
trim: true,
},
lastName: {
type: String,
minlength: 3,
trim: true,
},
biography: {
type: String,
minlength: 5,
trim: true,
},
});
UserSchema.methods.toJSON = function () {
let user = this;
let userObject = user.toObject();
return _.pick(userObject, ["_id", "firstName", "email"]);
};
and this is my controller function
const controller = {
fetchUsers :async (_req, res) => {
try {
await User.find({})
.then((users) => {
res.status(200).send(users);
})
.catch((err) => {
res.status(400).send(err);
});
} catch (error) {
res.status(400).json({
Error: `something is wrong. ${error}`,
});
}
}
}
the result is that i tested in postman is :
[
{
"_id": "5fe26ba0d290a216c0fe6d5d"
},
{
"_id": "5fe26c8e40ca9a06b8c96259"
},
]
Don't use .then & await both . Try this once. Assuming model is correct.
const controller = {
fetchUsers :async (_req, res) => {
try {
const users=await User.find({}).exec()
if(users){
res.status(200).send(users);
}
else{
res.status(404).send("no user found");
};
} catch (error) {
res.status(500).json({
Error: `something is wrong. ${error}`,
});
}
}
}
problem is UserSchema.methods.toJSON method there isn't any email field, if we want to filter our output data it's better to filter it by mongoose.find({"condition"},{"fields"})
I'm have two schemas where one depends of the other to save.
const OrderSchema = new moongose.Schema({
product: {
type: moongose.Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: {
type: Number,
required: true,
default: 1,
},
total_price: {
type: Number,
}
})
OrderSchema.pre('save', async function(next) {
this.total_price = product.price * quantity
next()
})
const Order = moongose.model('Order', OrderSchema)
And the other:
const ProductSchema = new moongose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String
},
photo: {
data: Buffer,
contentType: String
}
})
const Product = moongose.model('Product', ProductSchema)
But when I try save one Order with one Product exiting in data base:
{
"product":"5cae6ff5d478882ed8725911",
"quantity":3
}
Show error: Error: ReferenceError: product is not defined
This is my controller to save a new Order:
router.post('/register', async (req, res) => {
try {
const order = await Order.create(req.body)
return res.send({ order })
}
catch (error) {
console.error('Error:', error)
}
})
I usually use
idproduct: {
type: moongose.Schema.ObjectId,
required: true
},
This way the post works correctly
LOL, I found the ERROR:
OrderSchema.pre('save', async function(next) {
this.total_price = product.price * quantity
next()
})
I forgot to use 'THIS', correct:
OrderSchema.pre('save', async function(next) {
this.total_price = this.product.price * this.quantity
next()
})
Hehehe, sorry guys...
I have the following code:
const Order = require('../../models/order');
const Product = require('../../models/product');
Order.find({}, '_id product quantity', function(err, result) {
if (result) {
const response = {
count: result.length,
createdOrder: result.map(function(order) {
return {
_id: order._id,
productId: order.product,
quantity: order.quantity,
request: {
type: 'GET',
url: 'http://localhost:3000/orders/' + order._id
}
}
})
};
res.status(200).json(response);
} else if (err) {
console.log(err);
res.status(404).json({
error: err
});
}
});
How to use populate method to give more information about the product in the above syntax?
In your Order Schema you should set up a ref:
const mongoose = require('mongoose');
const orderSchema = mongoose.Schema({
// ...,
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' }
});
module.exports = mongoose.model('Order', orderSchema);
Populate with product:
Order.find({})
.populate('product')
.exec()
.then(document => {
// handle the document...
});
Hope this helps!
Order.find({}, '_id product quantity', function (err, result) {
if (result) {
const response = {
count: result.length,
createdOrder: result.map(function (order) {
return {
_id: order._id,
productId: order.product,
quantity: order.quantity,
request: {
type: 'GET',
url: 'http://localhost:3000/orders/' + order._id
}
}
})
};
res.status(200).json(response);
}
else if (err) {
console.log(err);
res.status(404).json(
{
error: err
});
}
}).populate('product', '_id name price');
The populate method can be used in javascript syntax like the above.