I built an ordering system with Node JS and MongoDB, I want to calculate order total_price in server before save it as a new order,
let ref = (model) => {
return { type: mongoose.Schema.Types.ObjectId, required: true, ref: model };
};
this is my order model schema
{
items: [
{
id: ref("menu_item"),
count: String,
size: String,
options: [String],
},
],
total_price: String,
tip: String,
};
and this is menu_item model schema
{
name: String,
price: String,
vat: String, // 3%
size: [
{
name: String,
unit: String,
price: String,
vat: String, // 3%
in_stock: Boolean,
is_default: Boolean,
},
],
options: [
{
title: String,
options: [
{
name: String,
price: String,
vat: String, // 3%
in_stock: Boolean,
is_default: Boolean,
},
],
},
],
}
How it's possible?
this is some tried that I done but it's wrong way.
when customer send an order this function will be call
async (req, res) => {
let total = 0;
let size_price = 0;
let options_price = 0;
let {
items,
tip,
} = req.body;
let price = 0;
let item_price = items.forEach(async (el) => {
let menu_item = await req.models.menu_item.findOne({ _id: el.id });
price += parseInt(menu_item.price);
console.log(menu_item.price) // first 12 second 9
console.log(price) // first 12 second 21
});
console.log(price) // return 0
}
forEach loop does not wait for async functions to complete before executing next iteration / exiting the loop. In order to wait till all records are queried from DB and price value is updated, we can either wrap all promises in Promise.all or execute them serially in for-of loop.
Here is the updated code using Promise.all:
async (req, res) => {
let total = 0;
let size_price = 0;
let options_price = 0;
let {
items,
tip,
} = req.body;
let price = 0;
await Promise.all(items.map(async (el) => {
let menu_item = await req.models.menu_item.findOne({ _id: el.id });
price += parseInt(menu_item.price);
console.log(menu_item.price) // first 12 second 9
console.log(price) // first 12 second 21
})
);
console.log(price) // return 0
}
Related
I have a controller where I am trying to query the most popular posts within the last week, sorted by most popular, and has a max cap of 50 posts. I am trying to use the aggregate() method; however, I am not sure if I am doing it correctly. When I run the query In insomnia I get an error like so:
{
"ok": 0,
"code": 8000,
"codeName": "AtlasError"
}
Here is my post model:
const postSchema = mongoose.Schema({
title: {
type: String,
required: true
},
message: {
type: String,
required: true
},
//replace creator with name
name: String,
creator: String,
tags: [String],
size: String,
selectedFile: String,
likes: {
type: [String],
default: [],
},
comments: {
type: [String],
default: []
},
createdAt: {
type: Date,
default: new Date(),
},
dogTreats: {
type: Number,
default: 0,
required: false,
}
});
and here is my controller/post.js
export const getPopular = async (req, res) => {
//get current time
let currentTime = new Date()
//get from 7 days ago
currentTime.setDate(currentTime.getDate()-7)
console.log(currentTime) // -> output 2022-09-04T19:29:39.612Z
try {
//sort posts by most likes and within 7 days ago, but with a max of 50 posts
const mostPopular = await PostMessage.aggregate([{"$sort": { likes: -1}}, { "$limit": 50}, { "$gt": currentTime }])
res.status(200).json(mostPopular)
} catch (error) {
res.status(500).json(error)
}
}
You can use find method. It is better to use here.
If you need to reach a value from another table populated, aggregation is better to use. However, at here, find is the best way to reach datas.
const mostPopular = await PostMessage.find({createdAt: {$gt : currentTime}}).sort({likes: -1}).limit(50)
Try this aggregation
export const getPopular = async (req, res) => {
//get current time
let currentTime = new Date()
//get from 7 days ago
currentTime.setDate(currentTime.getDate() - 7)
console.log(currentTime) // -> output 2022-09-04T19:29:39.612Z
try {
//sort posts by most likes and within 7 days ago, but with a max of 50 posts
const mostPopular = await PostMessage.aggregate([
{ $match: { createdAt: { $gt: currentTime } } },
{ $sort: { likes: -1 } },
{ $limit: 50 }
])
res.status(200).json(mostPopular)
} catch (error) {
res.status(500).json(error)
}
}
I have schema for products and it has a field storeZones object in it defined as
...
storeZones: {
type: {
masterZone: {type: Schema.Types.ObjectId, model: 'Zone', index: 1 },
zone: { type: Schema.Types.ObjectId, model: 'Zone', index: 1 },
subZone: { type: Schema.Types.ObjectId, model: 'Zone', index: 1 },
},
default: {
masterZone: null,
zone: null,
subZone: null,
},
},
...
I am counting for products in a specific masterZone. So my query is
const condition = { 'storeZones.masterZone': masterZone };
console.log(condition); // { 'storeZones.masterZone': '60533e6a745d465ab6cb3fc9' }
const total = await Product.count(condition);
This returns 0 results.
But when i paste the exact query in mongo shell; Robo3t to be exact.
db.products.find({'storeZones.masterZone': ObjectId('60533e6a745d465ab6cb3fc9') } )
It produces the desired output. Can someone please provide some assistance?
Fixed it by converting the masterZone from request to an ObjectId. Idk why i needed to do this, but that fixed it! so...
const m = mongoose.Types.ObjectId(masterZone);
const condition = { 'storeZones.masterZone': m };
console.log(condition); // { 'storeZones.masterZone': '60533e6a745d465ab6cb3fc9'}
const total = await Product.count(condition);
Hi everyone I have an array of objects with some populated fields. This is the schema of the product.
import mongoose, { Schema } from 'mongoose';
const productSchema = new mongoose.Schema(
{
name: String,
description: String,
sku: String,
barcode: String,
isActive: Boolean,
quantity: Number,
availability: String,
taxClass: [{ type: Schema.Types.ObjectId, ref: 'TaxClass' }],
images: [{ type: Schema.Types.ObjectId, ref: 'Image' }],
variants: [{ type: Schema.Types.ObjectId, ref: 'Variant' }],
tags: [{ type: Schema.Types.ObjectId, ref: 'Tag' }],
price: {
comparePrice: Number,
price: Number
},
seo: {
name: String,
keywords: [
{
name: String
}
],
description: String,
image: String
}
},
{ timestamps: true }
);
const Product = mongoose.model('Product', productSchema);
export default Product;
So i have a function and I want to return all the products with the variant color of green.
export const returnFilteredProducts = async (_, { filters = null, page = 1, limit = 20 }, context) => {
await jwtAuthentication.verifyTokenMiddleware(context);
try {
let searchQuery = {};
const products = await Product.find(searchQuery).populate(['variants', 'tags', 'images', 'taxClass']);
console.log(products.filter((item) => item.variants.filter((e) => e.color.indexOf('green') >= 0)));
return {
products
};
} catch (error) {
handleError(error);
}
};
The thing is that it does not return me the document with a variant color of green, instead it returns all the documents.
I am implementing a filtering system so I don't filter the products with in the frontend with redux.
Regarding the filtering method that is applied into the products array:
products.filter((item) => item.variants.filter((e) => e.color.indexOf('green') >= 0))
Inner call item.variants.filter() returns an array.
The outer call: products.filter() will include the product item, since the array will coerce into true, even when empty.
You can use method Array.some() for the inner call,
which will return a boolean true if at least one item (e) in item.variants
has the desired color.
This way you will filter-out all the product items that do-not contain the desired color in at least one element of the item.variants array.
So I am trying to retrieve a course using its id. I've tried using:
Course.findOne({ _id: __id })
Course.findById(id)
I not sure why it's not working, do I have to define _id type in the schema?
Result:
null
Here is my schema + function
const courseSchema = new mongoose.Schema({
name: { type: String, required: true, minlength: 3, max: 255 },
category: {
type: String,
required: true,
enum: ["web", "mobile", "network"]
},
tag: [String],
data: Date,
author: String,
isPublished: Boolean,
price: {
type: Number,
required: function() {
return this.isPublished;
},
min: 10,
max: 200
},
__v: Number
});
const Course = mongoose.model("Course", courseSchema);
async function updateCourse(id) {
// var __id = mongoose.Types.ObjectId(id); // tried converting string id (?)
console.log(id);
// // method 1
const course = await Course.findOne({ _id: __id });
console.log("resulting...", course);
if (!course) return;
course.isPublished = true;
course.author = "Another author";
const result = await course.save();
console.log("saved....", result);
}
updateCourse("5c726f6feb352743f8226239");
MongoDB:
You should not use __id in your Course.findOne call - use _id: _id:
Course.findOne({_id: _id});
Try to replace __id with id.
Course.findOne({_id: id});
i'm making a web site with MEAN Stack
I made a schema.
below is the schema.
const StoreSchema = mongoose.Schema({
storename: {
type: String
},
storenumber: {
type: Number
},
product: [{
pname: String,
pcode: Number,
price: String,
detail: String
}]
});
product is array.
when i make this schema, mongoose make it like this.
_id:5c3afaa96649e84364aab24b
storenumber:1
product:Array
__v:0
now there is a problem .
i want to insert values to pname, pcode, price, detail in product array.
but i can't push the values to the array.
below is the inserting value code.
module.exports.addProd = function(newProd, callback) {
Store.updateOne({
storenumber: number
}, {
$push: {
pname: newProd.pname
},
$push: {
pcode: newProd.pcode
},
$push: {
price: newProd.price
},
$push: {
detail: newProd.detail
}
}, callback);
}
but it doesn't work.
even i wrote product.
the values in newProd are all correct
what i want is like this
product[0] = {
pname:blah,
pcode:1,
price:5,
detail:blah blah
}
how can i insert values to array in mongoose?
please help me
You have to push the whole object together rather than each field like this -
Store.updateOne({
storenumber: number
}, { $push: { "product": newProduct } }, callback);
and also rather than using callback you should use async await -
module.exports.addProd = async newProd => {
let res = await Store.updateOne({
storenumber: number
}, { $push: { "product": newProduct } });
return res;
}