How to post multiple array Nodejs - node.js

I need to post multiple array at the same time so i can achieve this :
{
name:"John Snow",
detail: [
{size: "M", total: 5, color: "red"},
{size: "S", total: 2, color: "black"}
]
}
i'm using dynamic form that can generate new input field for detail array. so this is my schema model :
const OrderSchema = new Schema({
name:{
type: String,
required: true
},
detail:[{
size:{},
color:{},
total:{}
}],
date:{
type: Date,
default: Date.now
}
});
this is my route post :
router.post('/add', (req, res) => {
let errors = [];
if (!req.body.name) {
errors.push({ text: 'Your customer name is empty' });
}
if (errors.length > 0) {
res.render('orders/add', {
errors: errors,
customer: req.body.name,
detail:[{
size: req.body.size,
color: req.body.color,
total: req.body.total
}]
});
} else {
const newUser = {
customer: req.body.name,
detail:[{
size: req.body.size,
color: req.body.color,
total: req.body.total
}
new Order(newUser)
.save()
.then(order => {
res.redirect('/');
})
}
});
submit post is work, it just the result is not what i want :
{
name:"John Snow",
detail: [
{size: ["M","S"], total: [5,2], color: ["red", "black"]}
]
}
i hope you can help me, thanks!

Let's assume you have your details in a request body.
The req.body.details would look like this:
details: [
{size: "M", total: 5, color: "red"},
{size: "S", total: 2, color: "black"}
]
You could then simply save it altogether like so:
detail: req.body.details
Note that your Schema for details is a bit odd:
detail:[{
size:{}, // seems to be a string not an object
color:{}, // seems to be a string not an object
total:{} // seems to be a number not an object
}]
Instead, I think you could do:
detail:[{
size:{type: String},
color:{type: String},
total:{type: Number}
}]
Edit:
Since you do not seem to validate the details, you could simply make it an array in your Schema (that is up to you and what works best).
detail: { type: Array }
In general req.body.details could come from wherever you make the request. It could be sorted and equal to the array that you want to save in the database.
I am not fully aware of what is in your req.body.size for example but if it is an array such as ["M","S"] then you would extract each element and create separate objects that you would then push to the array which you would be saving in your database.
Have a look below:
let size = ["M","S"]
let total = [5,2]
let color = ["red", "black"]
let detailsToDb = []
for (let i=0; i<size.length; i++) {
detailsToDb.push({
size: size[i],
color: color[i],
total: total[i]
})
}
console.log(detailsToDb)
In your case you could use req.body.size[i] etc. right away, no need to initialize the variables.
let detailsToDb = []
for (let i=0; i<req.body.size.length; i++) {
detailsToDb.push({
size: req.body.size[i],
color: req.body.color[i],
total: req.body.total[i]
})
}

Related

Parsing posted object array, Express

I need to parse data with Express from form:
invoiceRouter.post('/', async (req,res) => {
console.log(req.body);
let invoice = new Invoice();
invoice = req.body;
invoice.status = 0;
//save
res.redirect('/invoices');
});
When I log, the array of objects is read as list of values:
{
createdDate: '2021-10-15',
invoiceRows: [ 'Title3', '2', 'Title2', '3' ]
}
But it can not read the invoiceRows as array of 2, therefore I am struggling to parse it into array for saving it.
When I set the extended: false, I can see following result from req.body:
[Object: null prototype] {
createdDate: '2021-10-15',
'invoiceRows[0].productTitle': 'Title2',
'invoiceRows[0].unitPrice': '2',
'invoiceRows[1].productTitle': 'Title3',
'invoiceRows[1].unitPrice': '2'
}
The schema I am using:
const invoiceSchema = new mongoose.Schema({
createdDate: {
type: Date,
required: true
},
status: {
type: Number,
required: true
},
invoiceRows: [{
productTitle: String,
unitPrice: Number
}]
});
Question: what am I doing wrong, in order to get array of objects from req.body inside parent object?
In your req.body you should be receiving like bellow (As per your model schema). Make your front end to send data like bellow.
{
createdDate: '2021-10-15',
invoiceRows: [ { productTitle :'Title1', unitPrice : 2}, { productTitle :'Title2', unitPrice : 3} ]
}

implement a search functionality that query MongoDB database and return all the objects which contain a user given value in node js and express

I want to implement a search functionality that would query my MongoDB database and return all the objects which contain (full/partially) the name I am searching for.
Example:
My object collection is products, and I want to see every product which contains the name I search, from the product names.
My 'Products' collection looks like this...
[ { _id: 5f79,
productName: 'Test-image12345',
price: 60,
details: 'Test product' },
{ _id: 5f7d,
productName: 'Test-image1234',
price: 60,
details: 'Test product'},
{ _id: 5fv4,
productName: 'Test',
price: 60,
details: 'Test product'},
]
Now I need to find all the products with "Test-image1234"
// search a product by name
productRoute.get('/getproduct/:name', async (req,res) => {
try {
const findname = req.params.name;
const objs = await Product.find({productName:{ $regex:'.*'+findname+'.*'} });
res.json(objs);
} catch (error) {
res.json({message: error});
}
})
Now I get the answer as follows...
[ { _id: 5f79,
productName: 'Test-image12345',
price: 60,
details: 'Test product' },
{ _id: 5f7d,
productName: 'Test-image1234',
price: 60,
details: 'Test product'}
]

API to insert data to array of objects in mongoDB

I am trying to insert array of objects inside array of objects in my mongoDB schema. This is how i want my schema to appear.
const CourseSchema = mongoose.Schema({
categoryname: {
type: String,
required: "Course Category",
min: 3,
max: 100
},
coursename: {
type: String,
required: "Course Name",
min: 3,
max: 100
},
levels:
[
{
levelid: Number,
levelname: String,
chapter:
[
{
chapternumber: Number,
chaptername: String,
content: String //To be elaborated
}
]
}
]
});
My API which i have written looks like this:
exports.addcourse = (req, res) => {
let levels = [];
levels.push({
levelid: req.body.levelid,
levelname: req.body.levelname,
chapter: [
{
chapternumber: req.body.chapternumber,
chaptername: req.body.chaptername,
content: req.body.content
}
]
})
const newCourse = new Course({
coursename: req.body.coursename,
categoryname: req.body.categoryname,
levels: levels
});
newCourse.save(function (error) {
if (error) res.json({ message: 'could not add course because ' + error });
res.json({ newCourse: newCourse });
});
}
This works fine when i enter one level and one chapter, but gives an error when i enter multiple data.
I am giving input from postman 'x-www'form-urlencoded'.
please help.
The error i get when i add one more levelid and levelname in postman
{
"message": "could not add course because ValidationError: levels.0.levelid: Cast to Number failed for value \"[ '1', '2' ]\" at path \"levelid\", levels.0.levelname: Cast to String failed for value \"[ 'First Level', 'Second Level' ]\" at path \"levelname\""
}
The data i am trying to enter
In postman, when you are sending the same key levelid twice, it converts it to array containing both the values. Like in your case, in req.body.levelid, you will receive [1, 2]. But in your schema, levelid is expecting a number value. Also, you are reading it wrong in your API code. Instead of getting levelid and chapter seperately, you can get the levels array in request body with values levelid, levelname and chapter. Similarly, chapter can be an array of objects. req.body.levels will look like this:
[{
levelid: 1,
levelname: "level1",
chapter: [{
chapternumber: 1,
chaptername: "chapter1",
content: "chapter1-content"
}, {
chapternumber: 2,
chaptername: "chapter2",
content: "chapter2-content"
}]
}]
Try this in postman by giving input in raw

Id of object mus be removed based on matching req.params.id

router.delete('/shopping-cart/:id', (req, res) => {
let cart = new Cart(req.session.cart);
console.log(req.params.id);
console.log(cart.generateArray());
});
console.log will output the following result (req.params.id):
5c863cc8ee0819f989acf9c3
console.log will output the following result (cart.generateArray()):
[ { item:
{ _id: '5c863cc8ee0819f989acf9c3',
imagePath: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
title: 'Gothic Video',
description: 'Absolutely stunning',
price: 10,
__v: 0 },
image: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
qty: 1,
price: 10,
id: '5c863cc8ee0819f989acf9c3' } ]
So how do I loop through all the items and check if id matches the req.params.id. If that is the case, it should remove that object and then return an updated array on the client side.
let cards = [{
item: {
_id: '5c863cc8ee0819f989acf9c3',
imagePath: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
title: 'Gothic Video',
description: 'Absolutely stunning',
price: 10,
__v: 0,
},
image: 'https://upload.wikimedia.org/wikipedia/en/5/5e/Gothiccover.png',
qty: 1,
price: 10,
id: '5c863cc8ee0819f989acf9c3',
}]
cards.forEach(element => {
delete element.id
})
console.info(cards)
I assume that is coming from cart.generateArray()?
If so, you probably should do that inside the function in question, but if you can't, then just map the results to a new array:
let result = cart.generateArray().map(item => {
const {id, ...entry} = item;
// if you want to also remove _id from the inner item, you can do the same
return entry;
});
console.log(result); // will have entries w/o id in them.
If you're looking to remove the nested item object as well, it's the smae approach, though I'll change some words to improve readability.
let result = cart.generateArray().map(cartItem => {
const {id, item, ...entry} = cartItem;
// this will remove both the id and the item keys
return entry;
});
console.log(result); // will have entries w/o id in them.

Mongoose query doesn't work with where() when filtering by numeric values

So I am having trouble with queries using mongoose when using the where clause. They work when I filter on strings, but not with numbers.
Here is my model/schema:
// Schema
var Wheel = new mongoose.Schema({
name: String,
method: String,
size: Number,
width: Number,
weight: Number
});
// Model
var WheelModel = mongoose.model('Wheel', Wheel);
This query works:
var query = WheelModel.find();
query.where('method').equals('Cast/Spun');
query.limit(10);
query.exec(function (err, wheels) {
// wheel objects are returned
});
This is an example of a wheel object inside the array 'wheels'
{
"_id": "523de98b263add11a8d4fc4a",
"name": "AME Circlar RS",
"weight": 18.1,
"width": 7,
"method": "Cast/Spun",
"size": 15
}
This query below returns [], and does so for if I filter by size, width, and weight, and for any numbers
var query = WheelModel.find();
query.where('size').equals(15);
query.limit(10);
query.exec(function (err, wheels) {
if (!err) {
return res.send(wheels);
} else {
return console.log(err);
}
});
I have also tried
query.where('size', 15);
query.where('size', '15');
var query = WheelModel.find({ size: 15});
If I go:
query.where('size').ne(15);
Then I get results back, but they will include values where the size is 15. So I suspect I have some type issues, I just don't know what. Any help would be apprecicated!
Try the following schema it should work for you (as per understanding from your comments) with the same query i.e. query.where('size').equals(15)
var Wheel = new mongoose.Schema({
name: String,
method: String,
size: { type: Number },
width: { type: Number},
weight: { type: Number }
});
For more information, check this Schema Types in API docs.

Resources