Can't save Data in Json Format in Mongodb - node.js

In this application, I am saving semester_id, course_id and Subject in Mongodb. All I need is to save the Subject in Json format. I want to save semester_id , course_id and save Subject in Json(not in array) with same ids - For semeter and course. I am saving subject in array and I am new to Angular. Can anyone help me out. Thanks in advance.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SubjectSchema = new Schema({
semesterId:{type: String,ref:'semesterNew'},
courseId :{type: String,ref:'CollegeCourse'},
subject:{
subject :{ type:String}
},
createdOn : {type:Date,default:Date.now},
updatedOn : {type:Date,default:Date.now},
});
mongoose.model('Subject',SubjectSchema);
router.post('/addSubject',function(req,res){
var subjects = JSON.stringify(req.body.subject);
var subjectData = new subjectModel({
semesterId:req.body.semesterId,
courseId: req.body.courseId,
subject: subjects,
});
subjectData.save(function (err, result) {
if (err) {
console.error(err);
return res.status(400).json({
message: 'Bad Request'
});
} else {
res.json({
status: 200,
data: result
})
console.log('Check',result);
}
});
});
addSubject(item){
return this.api.post(`${this.apiController}/addSubject`,item);
}
saveSubject() {
const config = {
position: NbGlobalPhysicalPosition.BOTTOM_RIGHT
};
const formData = new FormData();
this.subjectMasterForm.controls.semesterCtrl.markAsDirty();
this.subjectMasterForm.controls.collegeCourseCtrl.markAsDirty();
// this.subjectMasterForm.controls.image.markAsDirty();
var all_subject_array = [];
if (this.subjectMasterForm.valid && this.subjectMasterForm.value.subjects.length > 0) {
if (this.semesterSubjectId == '' || this.semesterSubjectId == null || this.semesterSubjectId == 'undefined' || this.semesterSubjectId== undefined) {
var subjects_values = this.subjectMasterForm.value.subjects
var subjects_length = this.subjectMasterForm.value.subjects.length;
subjects_values.forEach(function (element) {
all_subject_array.push(element.name);
console.log('Check2',element.name);
});
this.overview_data = {
courseId: this.courseId,
semesterId:this.semesterId,
subject: all_subject_array,
semesterSubjectId: this.semesterSubjectId,
}
this.collegeTemplateApi.addSubject(this.overview_data).subscribe(data => {
if (data['status'] == 200) {
this.toasterService.show("Subject successfully Added!!!..", `Success`, config);
} else {
this.toasterService.show("Subject Already exists in our Database!!!...", `Success`, config)
}
});
} else {
if(this.courseId!=undefined && this.semesterId!=undefined){
if (this.subjectMasterForm.value.subjects.length > 0) {
var subjects_values = this.subjectMasterForm.value.subjects
var subjects_length = this.subjectMasterForm.value.subjects.length;
subjects_values.forEach(function (element) {
all_subject_array.push(element.name);
});
this.overview_data = {
courseId: this.courseId,
semesterId:this.semesterId,
subject: all_subject_array,
semesterSubjectId: this.semesterSubjectId
}
}
this.collegeTemplateApi.updateSubject(this.overview_data).subscribe(data => {
if (data['status'] == 200) {
this.toasterService.show("Subject successfully Updated!!!..", `Success`, config);
} else {
this.toasterService.show(data['message'], `Success`, config)
}
});
}
}
} else if (this.subjectMasterForm.value.subjects.length == 0) {
this.subjecterror = true;
}
setTimeout(() => this.ngOnInit(), 3000);
}

In your first code segment, the Subject model is not assigned to a variable.
mongoose.model('Subject',SubjectSchema);
Yet later in your code you declare a new instance of subjectModel.
Try assigning the model to this name.
var subjectModel = mongoose.model('Subject', SubjectSchema);

Related

The parameter name '' has already been declared. Parameter names must be unique

I have here an API created in NodeJS. When I run the API, it works on the first time, but if run it again its give me an error The parameter name Username has already been declared. Parameter names must be unique at Request.input. I checked other threads on how to fix this thing. Some answers that it needs to be cleared, but I think there is no function in NodeJS mssql library that clears parameter.(correct me if I'm wrong)
My code:
const res = require("express/lib/response")
const {sql,request} = require("../config/connection")
module.exports = {
checkExist: (data,callBack) => {
if(data.key == process.env.KEY) {
var username = data.username
var firstname = data.firstname
var middlename = data.middlename
var lastname = data.lastname
if(username == "" || firstname == "" || middlename == "" || lastname == "") {
return callBack("Invalid Input")
}
else {
request.input('Username', sql.VarChar(50), username);
request.input('FirstName', sql.VarChar(50), firstname);
request.input('MiddleName', sql.VarChar(50), middlename);
request.input('LastName', sql.VarChar(50), lastname);
request.output('Result', sql.Int);
request.execute('sp_INS_User').then(function(recordsets, returnValue, affected) {
if(recordsets.output.Result == -100) {
return callBack("Player Exist with different Username")
}
else if(recordsets.output.Result == -4) {
return callBack("Something went wrong while processing your request, please try again later.")
}
else {
if(recordsets.output.Result == 1000) {
return callBack(null,recordsets)
}
}
// console.dir(err);
}).catch(function(err) {
//return callBack(err)
return callBack("Something went wrong while processing your request, please try again later.")
});
}
}
else {
return callBack("Invalid Access")
}
}
}
My code in : ../config/connection/
const sql = require("mssql")
require("dotenv").config()
const sqlConfig = {
user: process.env.USER,
password: process.env.PASS,
database: process.env.DB_MAIN,
server: process.env.HOST,
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt:false,
trustServerCertificate: true
}
}
const con = sql.connect(sqlConfig).then(function() {
console.log(`Database connection successful!`);
}).catch(function(err) {
console.log(`Database connection ${err}!`);
});
const request = new sql.Request();
module.exports = {
sql,request
}
This looks like an issue of reusing the request object so the second time this function gets called, you're using the same request object that was previously used the first time this function was called. As such, you're registering duplicate names with request.input().
Apparently, you will need a new copy of const request = new sql.Request(); each time you want to use it because the error message is telling you that you can't repeat statements like request.input('Username',...) over and over on the same request object. So, export a function to get a new request object rather than exporting just one pre-made object.
You can do that like this:
../config/connection/
const sql = require("mssql")
require("dotenv").config()
const sqlConfig = {
user: process.env.USER,
password: process.env.PASS,
database: process.env.DB_MAIN,
server: process.env.HOST,
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt:false,
trustServerCertificate: true
}
}
const con = sql.connect(sqlConfig).then(function() {
console.log(`Database connection successful!`);
}).catch(function(err) {
console.log(`Database connection ${err}!`);
});
const getRequest = function() { return new sql.Request(); };
module.exports = {
sql, getRequest
};
And, your other code:
const res = require("express/lib/response")
const { sql, getRequest } = require("../config/connection")
module.exports = {
checkExist: (data, callBack) => {
const request = getRequest();
if (data.key == process.env.CAMS_INPLAY_KEY) {
var username = data.username
var firstname = data.firstname
var middlename = data.middlename
var lastname = data.lastname
if (username == "" || firstname == "" || middlename == "" || lastname == "") {
return callBack("Invalid Input")
} else {
request.input('Username', sql.VarChar(50), username);
request.input('FirstName', sql.VarChar(50), firstname);
request.input('MiddleName', sql.VarChar(50), middlename);
request.input('LastName', sql.VarChar(50), lastname);
request.output('Result', sql.Int);
request.execute('sp_INS_User').then(function(recordsets, returnValue, affected) {
if (recordsets.output.Result == -100) {
return callBack("Player Exist with different Username")
} else if (recordsets.output.Result == -4) {
return callBack(
"Something went wrong while processing your request, please try again later."
)
} else {
if (recordsets.output.Result == 1000) {
return callBack(null, recordsets)
}
}
// console.dir(err);
}).catch(function(err) {
//return callBack(err)
return callBack(
"Something went wrong while processing your request, please try again later."
)
});
}
} else {
return callBack("Invalid Access")
}
}
}

google cloud function error DEADLINE EXCEEDED

I'm trying to write a simple pub/sub triggered cloud function to update my Firestore collection of stocks.I'm getting a bunch of weird error messages with one prominent of Error: 4 DEADLINE_EXCEEDED: Deadline exceeded. Whats even more strange that some stocks gets updated correctly while others don't. Im new to Javascript/Typescript so obviously I have some misunderstanding about how to return promises in this case here. The idea here is very simple loop through each ticker in the collection make a request to updated data then update existing document data and save it
export const updateChart = functions.pubsub.schedule('35 16 * * 1-5').timeZone('America/New_York').onRun(async(_context) => {
const key = functions.config().services.key as string
const db = admin.firestore()
const charts5DRef = db.collection("charts5D")
var needsUpdate : boolean = true
// I cut off some unrelated code for brevity sake
if (needsUpdate){
const snapshot = await charts5DRef.get()
var path = ``
const timestamp = Date.now() / 1000
return snapshot.forEach(async function(document){ // this could contain 100's of stock tickers
const ticker = document.id
const docData = document.data()
var labels = docData.labels as [string]
var marketNotional = docData.marketNotional as [number]
var marketTrades = docData.marketNumberOfTrades as [number]
var dates = docData.dates as [string]
var closings = docData.close as [number]
var volume = docData.marketVolume as [number]
path = `apiUrl to get data`
const options = {
method : 'GET',
uri : path,
resolveWithFullResponse : true,
}
await req(options).then(async(response)=>{
if(response.statusCode === 200){
const resultData = JSON.parse(response.body)
const updatedPrices = resultData as [IntradayPrice]
updatedPrices.forEach(function(value){
if(value.close !== undefined){
closings.splice(0,1)
marketTrades.splice(0,1)
marketNotional.splice(0,1)
labels.splice(0,1)
dates.splice(0,1)
volume.splice(0,1)
closings.push(value.close)
dates.push(value.date)
if(value.label !== undefined){ labels.push(value.label) } else { labels.push("") }
if(value.marketNotional !== undefined) { marketNotional.push(value.marketNotional) } else { marketNotional.push(0) }
if(value.marketNumberOfTrades !== undefined) { marketTrades.push(value.marketNumberOfTrades) } else { marketTrades.push(0) }
if(value.marketVolume !== undefined) { volume.push(value.marketVolume) } else { volume.push(0) }
}
})
await charts5DRef.doc(ticker).set({lastUpdate : timestamp,close : closings, labels : labels, marketVolume : volume,marketNumberOfTrades : marketTrades, marketNotional : marketNotional, dates : dates}).then(()=>{
console.log(`Updated ${ticker} 5Dchart successfully`)
}).catch((error)=>{
console.log(error)
})
}
}).catch((error)=>{
console.log(error)
})
})
}else{
console.log("Markets closed")
return
}
})
ok so this solved the errors
export const updateChart = functions.pubsub.schedule('35 16 * * 1-5').timeZone('America/New_York').onRun(async(_context) => {
const key = functions.config().services.key as string
const db = admin.firestore()
const charts5DRef = db.collection("charts5D")
var needsUpdate : boolean = false
if (needsUpdate){
const snapshot = await charts5DRef.get()
var path = ``
const timestamp = Date.now() / 1000
const promises : bird<void>[] = []
snapshot.forEach(async function(document){
const ticker = document.id
const docData = document.data()
var labels = docData.labels as [string]
var marketNotional = docData.marketNotional as [number]
var marketTrades = docData.marketNumberOfTrades as [number]
var dates = docData.dates as [string]
var closings = docData.close as [number]
var volume = docData.marketVolume as [number]
path = `https://cloud.iexapis.com/stable/stock/${ticker}/intraday-prices?token=${key}&chartInterval=10`
const options = {
method : 'GET',
uri : path,
resolveWithFullResponse : true,
}
const promise = req(options).then(async(response)=>{
if(response.statusCode === 200){
const resultData = JSON.parse(response.body)
const updatedPrices = resultData as [IntradayPrice]
updatedPrices.forEach(function(value){
if(value.close !== undefined){
closings.splice(0,1)
marketTrades.splice(0,1)
marketNotional.splice(0,1)
labels.splice(0,1)
dates.splice(0,1)
volume.splice(0,1)
closings.push(value.close)
dates.push(value.date)
if(value.label !== undefined){ labels.push(value.label) } else { labels.push("") }
if(value.marketNotional !== undefined) { marketNotional.push(value.marketNotional) } else { marketNotional.push(0) }
if(value.marketNumberOfTrades !== undefined) { marketTrades.push(value.marketNumberOfTrades) } else { marketTrades.push(0) }
if(value.marketVolume !== undefined) { volume.push(value.marketVolume) } else { volume.push(0) }
}
})
await charts5DRef.doc(ticker).set({lastUpdate : timestamp,close : closings, labels : labels, marketVolume : volume,marketNumberOfTrades : marketTrades, marketNotional : marketNotional, dates : dates}).then(()=>{
console.log(`Updated ${ticker} 5Dchart successfully`)
}).catch((error)=>{
console.log(error)
})
}
}).catch((error)=>{
console.log(error)
})
promises.push(promise)
})
return Promise.all(promises).then(()=>{
console.log("All good")
}).catch((error)=>{
console.log(error)
})
}else{
console.log("Markets closed")
return
}
})

How to resolve the promise and return the data back to where it was called?

I am really struggling with how to get the results of getAVPPlayerInfo() returned to the place where it is called (from the generatePlayersArray function on this line: var avpinfo = getAVPPlayerInfo(pinfo);
I've been using the code before this without generatePlayersArray() and getAVPPlayerInfo(), but the player data didn't need to be updated before. I have seen people change the line to var avpinfo = await getAVPPlayerInfo(pinfo); but that doesn't fix the problem.
How can I change this to fix the disconnect between these two functions?
// creates an order with all cart items and user info
var userNewOrder = function(charge, cart, callback) {
console.log('Saving customer ORDER for charge', charge.id);
Order.create({
cart: {
username: cart.username,
items: cart.items,
totalQty: cart.totalQty,
totalPrice: cart.totalPrice
},
customer: cart.customerID,
paymentID: charge.id,
createdOn: new Date(),
paymentStatus: 'PAID',
user: cart.username
})
.then(function(order) {
console.log('Order created!', order._id);
saveUserRegistrations(order, callback);
})
.catch(function(err) {
console.log('Error creating order', err);
callback(err);
});
};
// manipulate the data to prepare for registration data
var saveUserRegistrations = function(order, callback) {
console.log('Saving registrations from order', order.id);
//put cart items into array of objects
var registrations = generateRegistrationsArray(order);
// console.log("Registrations ",registrations);
var paymentId = order.paymentID;
var userobject = order.user;
// add paymentid to arrays
for (var i in registrations) {
registrations[i].paymentID = paymentId;
registrations[i].users = userobject;
for (var x in registrations[i].players) {
console.log(registrations[i].players[x]);
}
}
console.log(
'Registrations with payment ID and username added',
registrations
);
saveRegistrations(registrations, callback);
};
// generates the registrations array from the cart items
var generateRegistrationsArray = function(order) {
console.log('Generating array from cart items');
var arr = [];
for (var i = 0; i < order.cart.items.length; i++) {
var players = generatePlayersArray(order.cart.items[i]);
console.log('Players: ', players);
// create registration, using new players array
arr.push({
event: order.cart.items[i].event,
field: order.cart.items[i].field,
day: order.cart.items[i].day,
division: order.cart.items[i].division,
level: order.cart.items[i].level,
group: order.cart.items[i].group,
numplayers: order.cart.items[i].numberofplayers,
price: order.cart.items[i].price,
players: players,
createdOn: new Date(),
net: null,
team: null,
notes: null,
paymentNote: null,
waiversSent: false,
reviewed: false,
active: true
});
console.log('Registrations:', arr);
}
console.log('Registrations array', JSON.stringify(arr));
return arr;
};
// generates the player array from the cart and AVP info
var generatePlayersArray = function(items) {
console.log('Generating players array from cart items');
var parr = [];
for (var i = 0; i < items.players.length; i++) {
var pinfo = {
last: items.players[i].last,
avp_id: items.players[i].avp_id
};
var avpinfo = getAVPPlayerInfo(pinfo);
console.log('AVP info returned', avpinfo);
// create registration, using new players array
parr.push({
first: avpinfo.first || items.players[i].first,
last: avpinfo.last || items.players[i].last,
email: items.players[i].email,
address: avpinfo.address || items.players[i].address,
city: avpinfo.city || items.players[i].city,
state: avpinfo.state || items.players[i].state,
zip: avpinfo.zip || items.players[i].zip,
country: items.players[i].country,
phone: avpinfo.phone || items.players[i].phone,
signed: false,
sandbagger: false,
waivers: [],
createdOn: new Date(),
adult: avpinfo.adult || items.players[i].adult,
avp_id: items.players[i].avp_id,
ranking: items.players[i].ranking,
overallRanking: items.players[i].overallRanking,
shirt_size: items.players[i].shirtSize
});
console.log(parr);
}
console.log('Players array', JSON.stringify(parr));
return parr;
};
// get AVP data to update player info
var getAVPPlayerInfo = function(pinfo) {
console.log('Admin AVP API begin', pinfo);
avp_id = pinfo.avp_id;
last = pinfo.last;
// GET THE AVP DATA
var options = {
uri: `http://api.volleyamerica.com/VAREST.svc/V6rHHdPO/players/${avp_id}`,
headers: {
'User-Agent': 'Request-Promise'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(function(resp) {
console.log('Player has data', resp);
let avp = {};
let address = resp.Address1 || null;
if (resp.Address2) {
address += ` ${resp.Address2}`;
}
// GET AVP member data (shirt size and ranking for db)
avp.avp_id = avp_id;
avp.shirtSize = resp.AdultShirtSize;
avp.first = resp.FirstName;
avp.last = resp.LastName;
avp.email = resp.Email || null;
avp.phone = resp.HomePhone || null;
avp.address = address || null;
avp.signed = false;
avp.sandbagger = false;
avp.waivers = [];
avp.city = resp.City || null;
avp.state = resp.State || null;
avp.zip = resp.Zip || null;
// get overallRankings greater than 0
avp.overallRanking = _.pickBy(
_.get(resp, 'OverallRanking', {}),
(ranking, key) => {
return ranking > 0;
}
);
// get rankings greater than 0
avp.ranking = _.pickBy(_.get(resp, 'Ranking', {}), (ranking, key) => {
return ranking > 0;
});
let adult = null;
// if player is under 18
const birthday = moment(resp.Birthdate, 'M/D/YYYY');
age = moment().diff(birthday, 'years', false);
if (age < 18) {
avp.adult = false;
} else {
avp.adult = true;
}
console.log('AVP API SUCCESS, returning avp data ', avp);
return avp;
})
.catch(function(err) {
console.log('AVP data error', err);
});
};
//save registrations to the database
var saveRegistrations = function(registrations, callback) {
console.log('SAVING REGISTRATIONS TO DB', registrations);
// var reginfo = registrations;
Registration.collection
.insert(registrations)
.then(function(r) {
console.log('Successfully saved registrations!', r.insertedCount);
nodemailerConfirmation(registrations, callback);
})
.catch(function(err) {
console.log(err);
for (var i in err.writeErrors) {
console.log(err.writeErrors[i].errmsg);
}
callback(err.message);
});
};
// creates an order with all cart items and user info
var userNewOrder = function(charge, cart, callback) {
console.log('Saving customer ORDER for charge', charge.id);
Order.create({
cart: {
username: cart.username,
items: cart.items,
totalQty: cart.totalQty,
totalPrice: cart.totalPrice
},
customer: cart.customerID,
paymentID: charge.id,
createdOn: new Date(),
paymentStatus: 'PAID',
user: cart.username
})
.then(function(order) {
console.log('Order created!', order._id);
saveUserRegistrations(order, callback);
})
.catch(function(err) {
console.log('Error creating order', err);
callback(err);
});
};
// manipulate the data to prepare for registration data
var saveUserRegistrations = async function(order, callback) {
console.log('Saving registrations from order', order.id);
//put cart items into array of objects
var registrations = await generateRegistrationsArray(order);
// console.log("Registrations ",registrations);
var paymentId = order.paymentID;
var userobject = order.user;
// add paymentid to arrays
for (var i in registrations) {
registrations[i].paymentID = paymentId;
registrations[i].users = userobject;
for (var x in registrations[i].players) {
console.log(registrations[i].players[x]);
}
}
console.log(
'Registrations with payment ID and username added',
registrations
);
saveRegistrations(registrations, callback);
};
// generates the registrations array from the cart items
var generateRegistrationsArray = async function(order) {
console.log('Generating array from cart items');
var arr = [];
for (var i = 0; i < order.cart.items.length; i++) {
var players = await generatePlayersArray(order.cart.items[i]);
console.log('Players: ', players);
// create registration, using new players array
arr.push({
event: order.cart.items[i].event,
field: order.cart.items[i].field,
day: order.cart.items[i].day,
division: order.cart.items[i].division,
level: order.cart.items[i].level,
group: order.cart.items[i].group,
numplayers: order.cart.items[i].numberofplayers,
price: order.cart.items[i].price,
players: players,
createdOn: new Date(),
net: null,
team: null,
notes: null,
paymentNote: null,
waiversSent: false,
reviewed: false,
active: true
});
console.log('Registrations:', arr);
}
console.log('Registrations array', JSON.stringify(arr));
return arr;
};
// generates the player array from the cart and AVP info
var generatePlayersArray = async function(items) {
console.log('Generating players array from cart items');
var parr = [];
for (var i = 0; i < items.players.length; i++) {
var pinfo = {
last: items.players[i].last,
avp_id: items.players[i].avp_id
};
var avpinfo = await getAVPPlayerInfo(pinfo);
console.log('AVP info returned', avpinfo);
// create registration, using new players array
parr.push({
first: avpinfo.first || items.players[i].first,
last: avpinfo.last || items.players[i].last,
email: items.players[i].email,
address: avpinfo.address || items.players[i].address,
city: avpinfo.city || items.players[i].city,
state: avpinfo.state || items.players[i].state,
zip: avpinfo.zip || items.players[i].zip,
country: items.players[i].country,
phone: avpinfo.phone || items.players[i].phone,
signed: false,
sandbagger: false,
waivers: [],
createdOn: new Date(),
adult: avpinfo.adult || items.players[i].adult,
avp_id: items.players[i].avp_id,
ranking: items.players[i].ranking,
overallRanking: items.players[i].overallRanking,
shirt_size: items.players[i].shirtSize
});
console.log(parr);
}
console.log('Players array', JSON.stringify(parr));
return parr;
};
// get AVP data to update player info
var getAVPPlayerInfo = function(pinfo) {
console.log('Admin AVP API begin', pinfo);
avp_id = pinfo.avp_id;
last = pinfo.last;
// GET THE AVP DATA
var options = {
uri: `http://api.volleyamerica.com/VAREST.svc/V6rHHdPO/players/${avp_id}`,
headers: {
'User-Agent': 'Request-Promise'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(function(resp) {
console.log('Player has data', resp);
let avp = {};
let address = resp.Address1 || null;
if (resp.Address2) {
address += ` ${resp.Address2}`;
}
// GET AVP member data (shirt size and ranking for db)
avp.avp_id = avp_id;
avp.shirtSize = resp.AdultShirtSize;
avp.first = resp.FirstName;
avp.last = resp.LastName;
avp.email = resp.Email || null;
avp.phone = resp.HomePhone || null;
avp.address = address || null;
avp.signed = false;
avp.sandbagger = false;
avp.waivers = [];
avp.city = resp.City || null;
avp.state = resp.State || null;
avp.zip = resp.Zip || null;
// get overallRankings greater than 0
avp.overallRanking = _.pickBy(
_.get(resp, 'OverallRanking', {}),
(ranking, key) => {
return ranking > 0;
}
);
// get rankings greater than 0
avp.ranking = _.pickBy(_.get(resp, 'Ranking', {}), (ranking, key) => {
return ranking > 0;
});
let adult = null;
// if player is under 18
const birthday = moment(resp.Birthdate, 'M/D/YYYY');
age = moment().diff(birthday, 'years', false);
if (age < 18) {
avp.adult = false;
} else {
avp.adult = true;
}
console.log('AVP API SUCCESS, returning avp data ', avp);
return avp;
})
.catch(function(err) {
console.log('AVP data error', err);
});
};
//save registrations to the database
var saveRegistrations = function(registrations, callback) {
console.log('SAVING REGISTRATIONS TO DB', registrations);
// var reginfo = registrations;
Registration.collection
.insert(registrations)
.then(function(r) {
console.log('Successfully saved registrations!', r.insertedCount);
nodemailerConfirmation(registrations, callback);
})
.catch(function(err) {
console.log(err);
for (var i in err.writeErrors) {
console.log(err.writeErrors[i].errmsg);
}
callback(err.message);
});
};
Check the above code.

display 2 two table records in nodejs

I have tow MongoDB collection.
1) users
2) reviews.
at the first collection, I have stored username and id. and 2nd table I have stored user_id and comments and star rating.
I want to display on listing page users and his reviews.
I have written below code but it is not working.
var getTopSellers = function () {
var defer = Q.defer();
User.find({ isRegistered: true }).sort({ updatedAt: -1 }).limit(10).exec(function (err, sellers) {
if (!err) {
if (sellers && sellers.length > 0) {
for (var i = 0; i < sellers.length; i++) {
var sellerDetails = {};
var tempObj = {};
try {
tempObj.reviews = getreviews(sellers[i]._id);
sellerArr.push(tempObj);
} catch (e) {
// console.log("catch error:-", e);
}
}
out = U.getJson(C.SUCCESS_CODE, C.SUCCESS, sellerArr);
defer.resolve(out);
} else {
out = U.getJson(C.KNOWN_ERROR_CODE, 'No data found');
defer.reject(out);
}
} else {
console.log("Error:-", err);
out = U.getJson(C.ERROR_CODE, C.INETRNAL_SERVER_ERROR, b, err);
defer.reject(out);
}
})
return defer.promise;
};
var getreviews = function (user_id) {
var defer = Q.defer();
Review.find({ user_type: user_id }).sort({ updatedAt: -1 }).limit(10).exec(function (err, reviews) {
if (!err) {
if (reviews && reviews.length > 0) {
out = U.getJson(C.SUCCESS_CODE, C.SUCCESS, reviews);
defer.resolve(out);
} else {
out = U.getJson(C.KNOWN_ERROR_CODE, 'No data found');
defer.reject(out);
}
} else {
console.log("Error:-", err);
out = U.getJson(C.ERROR_CODE, C.INETRNAL_SERVER_ERROR, b, err);
defer.reject(out);
}
})
return defer.promise;
};
Please suggest

How to send a response only after a query has been executed in loopback

I have a remote method in loopback like:
Alerts.getAlertDetails = function (alertId, options, cb) {
var response = {};
var userId = options.accessToken.userId;
Alerts.app.models.MobileUserAlertRelation.find({where: {userId: userId, alertId: alertId, isDeleted: -1}, include: {relation: 'alerts', scope: {include: ['alertTypes'], where: {status: 1}}}}, function (err, alertRel) {
if (alertRel.length > 0 && alertRel[0].alerts()) {
response.code = 200;
response.status = "success";
response.data = {};
if (alertRel[0].alertId) {
response.data.alertId = alertRel[0].alertId;
}
if (alertRel[0].readStatus) {
response.data.readStatus = alertRel[0].readStatus;
}
if (alertRel[0].receivedOn) {
response.data.alertReceivedOn = alertRel[0].receivedOn;
}
var alertData = alertRel[0].alerts();
if (alertData.title) {
response.data.alertTitle = alertData.title;
}
if (alertData.message) {
response.data.alertShortMessage = alertData.message;
}
if (alertData.extraMessage) {
response.data.alertMessage = alertData.extraMessage;
}
if (alertData.priority) {
response.data.alertPriority = alertData.priority;
}
if (alertData.validUntil) {
response.data.alertExpiresOn = alertData.validUntil;
}
if (alertData.images && alertData.images.length > 0) {
response.data.alertImages = [];
for (var image in alertData.images) {
if (alertData.images.hasOwnProperty(image)) {
response.data.alertImages.push(constants.ALERT_IMAGE_URL + '/' + alertData.images[image]);
}
}
}
if (alertData.alertTypes() && alertData.alertTypes().alertTypeName) {
response.data.alertType = alertData.alertTypes().alertTypeName;
}
if (alertData.alertLocations && alertData.alertLocations > 0) {
response.data.alertLocations = [];
response.data.policeDepartments = [];
response.data.hospitals = [];
response.data.fireDepartments = [];
var locations = alertData.alertLocations;
for (var locKey in locations) {
if (locations.hasOwnProperty(locKey)) {
if (locations[locKey].data) {
response.data.alertLocations.push(locations[locKey].data);
console.log(locations[locKey].data);
if (locations[locKey].data.type) {
var locationType = locations[locKey].data.type;
if (locationType === "Polygon") {
var coordinates = locations[locKey].data.coordinates[0];
var polygonCenter = getPolygonCenter(coordinates);
console.log(polygonCenter);
}
}
}
}
}
}
cb(null, response);
} else {
response.code = 404;
response.status = 'error';
response.message = 'Alert not found.';
cb(null, response);
}
})
};
But when I call this method through api, response is received without data added from the complex code part. I know that callback will be called asynchronously here and so that cb(response) will be called before the complex code is executed completely. How can i send response only after the complex part is completed and data is correctly added to response from that data. I cannot move cb(response) inside the complex part as data is being pushed in for loop.
I have heard of promises, can it be used here, if so, how could it be done?
Someone please help!!
The problem is because of fetching relation in if.
The relation method is an async.
Alerts.getAlertDetails = function (alertId, options, cb) {
var response = {};
var userId = options.accessToken.userId;
Alerts.app.models.MobileUserAlertRelation.find({where: {userId: userId, alertId: alertId, isDeleted: -1}, include: {relation: 'alerts', scope: {include: ['alertTypes'], where: {status: 1}}}}, function (err, alertRel) {
if(alertRel.length < 1){
return handleError();
}
alertRel[0].alerts(handleResponse);
function handleResponse(err, alertRelAlert){
if(err) return handleError();
if (alertRelAlert) {
//all that code in question if if section
}else {
return handleError();
}
}
function handleError(){
response.code = 404;
response.status = 'error';
response.message = 'Alert not found.';
cb(null, response);
}
});
}

Resources