Parsing arrays within array for email in Node.js - node.js

I am submitting an array that contains nested arrays from Angular to a server running Node.js. I would like to parse each field so I can include it in a confirmation email. I'm not sure how to get the key/values from the array and put them in the email body.
I've tried var email = req.body.email for the items one level deep and var cost = req.body.detail.cost for the nested items two levels deep, but those don't seem to work.
Any suggestions?
Here's the Javascript:
router.post('/', function(req, res) {
if (err) {
res.status(402).send(err.message);
}
else {
console.log(JSON.stringify(req.body, null, 2));
var data = {
from: storefront#example.com,
to: email,
subject: 'Your Order Confirmation',
text: 'Thank you for your order. Below is your invoice:\n\n'+
'Name: '+ firstName + ' ' + lastName +
'Address: ' + address + ', ' + city + ', ' + state.code +'\n\n'+
'Item Description Cost\n\n'+
item + description + cost
// want to add the item, description, and cost for each item ordered
// . . .
var mailgun = new Mailgun({apiKey: api_key, domain: domain});
mailgun.messages().send(data, function (err, body) {
if (err) {
console.log('error');
}
else {
console.log('email sent!');
}
})
};
This is what the array looks like this:
[
[
{
"firstName": "John",
"lastName": "Doe",
"address": "555 Broadway",
"city": "New York",
"email": "john#example.com",
"phone": "2125551212",
"state": {
"code": "NY",
"state": "New York"
},
"timestamp": {
"addedAt": 1443911047642
},
"zip": "10001",
"$id": "-K-jnWa0IBiGCAInbaIr",
}
],
[
{
"item": "Pants",
"description": "Wranglers",
"timestamp": {
"addedAt": 1443911007264
},
"detail": {
"cost": 60,
"size": "36"
},
"$id": "-K-jnMj64LS-XMM18J-8",
},
{
"item": "Pants",
"description": "Levi's",
"timestamp": {
"addedAt": 1443911018026
},
"detail": {
"cost": 80,
"size": "33"
},
"$id": "-K-jnPMJDLJMKIH4rAUe",
}
]
]

I have had same problem....this will solve it.
var cartContent = req.body.slice(1);
//produces new array sans user contact information assuming you pushed it to the front of the array at some point....please do so!
Access properties like this for user contact content
req.body[0].name
For the cart items, it's much easier to loop through or manipulate cartContent sans the UN-releated user contact info object.
cartContent[0].item

Related

MongoDB $and query only works on Strings

I want to filter out data based on search criteria in mongoDb.
Here is the query:
exports.getParkingListByCriteria = async (req, res) => {
const cityQuery = req.body.city;
const stateQuery = req.body.state;
const countryQuery = req.body.country;
const zipQuery = req.body.zipCode;
try {
const filter = await Parking.find({
$and: [
{
"location.city": { $regex: new RegExp(cityQuery, ($options = "i")) },
"location.state": { $regex: new RegExp(stateQuery, ($options = "i"))},
"location.country": { $regex: new RegExp(countryQuery, ($options = "i"))},
"location.zipCode": zipQuery,
},
],
});
res.status(200).send(filter);
} catch (error) {
return res.status(500).json({ error: error.message });
}
};
City, state and country are stored as a String and zipCode is stored as a Number in mongoose model.
city, state and country filter was just working fine. It was giving me an intended results but then I added a zipCode query and now city, state and countries filter is also giving an empty array.
request I am sending from postman:
{
"city": "edmund",
"state": "lousinia",
"country":"australia",
"zipCode": 49755
}
All are stored in a one collection like shown below:
{"_id": {"$oid": "62cc46e920782c4be0673d50"},
"merchantId": {"$oid": 62c950ebc96c2b690028be8b"},
"contactInfo": {"name": "Ronda Green", "phoneNumber": 9104933588},
"about": "Laborum non minim ad",
"location":
{"address": "349 scott avenue",
"city": "edmund",
"state": "louisiana",
"zipCode": 49755,
"country": "australia"},
"price": 18,
"parkingType": "parkingLot",
"parkingInfo": [{"parkingName": "College Place","_id":"$oid":"62cc46e920782c4be0673d51"},"default": []}],
"totalSpots": [168],
"parkingSpotType": ["Motorbike","Large"],
"coordinates":
{"lng": 1.522645,
"lat": 125.939061},
"status": "active",
"isFeePaid": false,
"availability": [],
"specialEvents": [],
"__v": 0}
Before the introduction of zipQuery to the code every individual request was working perfectly fine (Like if I pass a query { "city": "edmund" } it would give me above result) but after the zipQuery it just got messy.
The result of console.log(zipQuery) is 49755

How to filter mongoDB in NodeJS API, checking if values are included in objects in array

I am writing REST API in NodeJS with MongoDB. Structure of the database is:
[
{
"_id": "12345",
"name": "Meal name",
"category": "dessert",
"area": "british",
"imageUrl": "https.image.jpg",
"instructions": "some instructions...",
"ingredients": [
{
"name": "salt",
"measure": "1g"
},
{
"name": "chicken",
"measure": "1"
},
{
"name": "butter",
"measure": "90g"
}, ...
]
}, ...
]
I can write a route to get data which meet one condition,
i.e.:
//getting all, when category = :category
router.get('/meals/category=:category', async (req, res) => {
try {
const meals = await Meal.find({category: req.params.category})
res.json(meals)
} catch (err) {
res.status(500).json({ message: err.message })
}
})
Here, route
'meals/category=vegetarian'
get all data with category = vegetarian.
However, I want to have route, which will filter all data by parameters: category, area, ingredients.
For example:
meals/ingredients=salt,pepper&category=dessert&area=american
should return all data, which contains salt and pepper in array, and category = dessert.
another example:
meals/area=american&category=dessert
should return all data, where area=american and category=dessert
How can I write the router.get() method to achieve that?

How to build a search endpoint in a API to find and filter results from a database

In my Node API and MongoDB, I'm trying to build an endpoint to search for data in the DB and get back the results to the client. My search goal is to show results from the Profile collection and in that way, I can build my queries to search by first name, surname, company and the combination of it as an example:
GET search?fn=joe or ?ln=doe or ?cp=Company or ?fn=...&ln=...&cp=...
Practically I can search in different ways and I can get for example all the people working for a company as a result of a search.
I would like to understand how can I achieve that with Mongoose/MongoDB and add also to the query optional a limit/pagination for the coming results.
I tried to make some simple trials but I got stuck as I do not really get it how to proceed next.
const SearchController = {
async getQuery(req, res) {
try {
const { fn, ln, cp } = req.query;
const searchResult = await Profile.find({
$or: [
{ firstname: fn },
{ surname: ln },
{
experience: {
company: cp
}
}
]
});
res.status(200).json(searchResult);
} catch (err) {
res.status(500).json({ message: err.message });
}
}
};
The JSON of a profile:
{
"imageUrl": "https://i.pravatar.cc/300",
"posts": [
"5e3cacb751f4675e099cd043",
"5e3cacbf51f4675e099cd045",
"5e3cacc551f4675e099cd046"
],
"_id": "5e2c98fc3d785252ce5b5693",
"firstname": "Jakos",
"surname": "Lemi",
"email": "lemi#email.com",
"bio": "My bio bio",
"title": "Senior IT developer",
"area": "Copenhagen",
"username": "Jakos",
"experience": [
{
"image": "https://via.placeholder.com/150",
"createdAt": "2020-02-04T13:47:37.167Z",
"updatedAt": "2020-02-04T13:47:37.167Z",
"_id": "5e3975f95fbeec9095ff3d2f",
"role": "Developer",
"company": "Google",
"startDate": "2018-11-09T23:00:00.000Z",
"endDate": "2019-01-05T23:00:00.000Z",
"area": "Copenhagen"
},
{
"image": "https://via.placeholder.com/150",
"createdAt": "2020-02-04T13:59:27.412Z",
"updatedAt": "2020-02-04T13:59:27.412Z",
"_id": "5e3978bf5e399698e20c56d4",
"role": "Developer",
"company": "IBM",
"startDate": "2018-11-09T23:00:00.000Z",
"endDate": "2019-01-05T23:00:00.000Z",
"area": "Copenhagen"
},
{
"image": "https://via.placeholder.com/150",
"createdAt": "2020-02-07T16:35:43.754Z",
"updatedAt": "2020-02-07T16:35:43.754Z",
"_id": "5e3d91dfb3a7610ec6ad8ee3",
"role": "Developer",
"company": "IBM",
"startDate": "2018-11-10T00:00:00.000Z",
"endDate": "2019-01-06T00:00:00.000Z",
"area": "Copenhagen"
}
],
"createdAt": "2020-01-25T19:37:32.727Z",
"updatedAt": "2020-02-04T23:14:37.122Z",
"__v": 0
}
The expected results are for example if I search the first name Joe I should get back all the profiles having as first name Joe. Similar for surname and company.
Please provide comments to allow me to understand if you need more scripts from the original code to see.
EDITED added the code modified of the search
// Models
const { Profile } = require("../models");
// Error handling
const { ErrorHandlers } = require("../utilities");
const SearchController = {
async getQuery(req, res) {
try {
const { fn, ln, cp } = req.query;
const query = {
$or: []
};
if (fn) query.$or.push({ firstname: fn });
if (ln) query.$or.push({ surname: ln });
if (cp) query.$or.push({ "experience.company": cp });
const searchResult = Profile.find(query, docs => {
return docs
});
if ((await searchResult).length === 0)
throw new ErrorHandlers.ErrorHandler(
404,
"Query do not provided any result"
);
res.status(200).json(searchResult);
} catch (err) {
res.status(500).json({ message: err.message });
}
}
};
module.exports = SearchController;
Have tried conditional query and modified your array search query for finding the company,
function findUser(fn, ln, cp) {
const query = {
$or: []
}
if (fn) query.$or.push({ firstname: fn })
if (ln) query.$or.push({ surname: ln })
if (cp) query.$or.push({ "experience.company": cp })
Profile.find(query, function (err, docs) {
if (err) {
console.error(err);
} else {
console.log(docs);
}
});
}
findUser("","","IBM")

Multiple records for nested/embedded schema is not getting inserted in mongodb, nodejs

Hi I am new to nodejs and mongodb, I have json file with below structure,
I have defined one shipment schema with the "comments" section as nested schema
{
"buyerId": "B58",
"sellerId": "SL8",
"comments": {
"title": "title5",
"body": "body5",
"date": "12-07-2017"
}
}
I have defined one function like below
exports.post = function(req, res) {
const comments = []
var s = new shipment();
s.sellerId = req.body.sellerId;
s.buyerId = req.body.buyerId;
s.poId = req.body.poId;
s.comments.push({
title: req.body.comments.title,
body: req.body.comments.body,
date: req.body.comments.date
});
s.save(function(err) {
if (err) {
res.send(err);
}
console.log("added");
res.send({
message: 'shipment Created !'
})
})
}
The above 'post' function will work properly when I have only one "comments" section, I mean the data gets properly
inserted into the mongodb as shown below
{
"_id": ObjectId("59689bc59058dbc812000002"),
"buyerId": "B58",
"sellerId": "SL8",
"comments": [{
"title": "title5",
"body": "body5",
"date": ISODate("2017-12-06T18:30:00Z"),
"_id": ObjectId("59689bc59058dbc812000003")
}],
"__v": 0
}
but when I have multiple "comments" section as shown below,
{
"buyerId": "B58",
"sellerId": "SL8",
"comments": [{
"title": "title5",
"body": "body5",
"date": "12-07-2017"
},
{
"title": "title8",
"body": "body7",
"date": "12-07-2017"
}
]
}
then no comments section gets inserted into the mongodb as shown below.
{
"_id": ObjectId("5968c04d4c02336800000002"),
"buyerId": "B57",
"sellerId": "SL7",
"comments": [{
"_id": ObjectId("5968c04d4c02336800000003")
}],
"__v": 0
}
what changes should I do in the function to get all the comments section being inserted into the mongodb properly ?
Instead of assigning value of every property, make instance and pass body directly into it.
const s = new shipment(req.body)
And then when you send data to the request, send in the following format
{ "buyerId": "B58", "sellerId": "SL8", "comments": [{ "title": "title5", "body": "body5", "date": "12-07-2017" }, { "title": "title8", "body": "body7", "date": "12-07-2017" } ] }
I tried like below and it worked.
for( var i = 0; i < req.body.comments.length; i++){
s.comments.push(
{ title: req.body.comments[i].title,
body : req.body.comments[i].body,
date : req.body.comments[i].date });
}
originally comments is an array in the second example comments is an array.
your function
s.comments.push({
title: req.body.comments.title,
body: req.body.comments.body,
date: req.body.comments.date
})
will only work if comments is an object. Put that in a for loop to make it work with arrays like so
for( var i = 0; i < req.body.comments.length; i++){
s.comments.push({
title: req.body.comments[i].title,
body: req.body.comments[i].body,
date: req.body.comments[i].date
})
}

find object inside JSON using nested ID

i have a mongo collection like this
{"stores": [{"name": "foo",
"songs": [ {"id": "", "name": "", "artist": "", "category": "", "tags": []} ],
"songsSchedule": [
{
"song_id": "",
"date": ,
"user": "",
"help": ,
"partners": [{"user": ""}],
"likes":
}
]
}]}
and i want to get the songs name and artist from the songsSchedule song_id, i've tried this but it's not working
var query = { _id: fn.generateID(req.params.store_id), songsSchedule: { $exists: true } };
var select = { songsSchedule:1 };
var array = [];
client("stores", function(err, collection) {
if (err)
return res.json(fn.status("30"));
collection.findOne(query, select, function(err, store) {
if (err || !store)
return res.json(fn.status("31"));
for (var i in store.songsSchedule) {
var song = store.songsSchedule[i];
array.push(song.song_id);
}
collection.find({ _id: fn.generateID(req.params.store_id), "songs._id": { $in: array } }, function(err, songs) {
res.json(songs);
});
});
});
and i dont really know if it's the best way of doing it
I'm not entirely clear what you mean by "get the songs name and artist from the songsSchedule song_id" but it looks like that query will be messy.
If it were me, I'd consider splitting out songs and songSchedule into their own collections for easier querying.
from your document example, the "songs" field contains documents that do not contain an "_id" field.
"songs": [ {"name": "", "artist": "", "category": "", "tags": []} ]
But, your find() query is querying on the "songs._id" field.
Also, I'm not too familiar with the json() method, but does it handle cursors?
Regards,
Kay

Resources