How to get an json object in JsonArray using Mongoose - json

I am trying to update a json object in an array using the following code. The code seems to be finding the json object in the array, however, it fails to update the json object inside the json array. It doesn't give any error so that's what makes it more confusing.
function addOrUpdateAppointment(jsonObject, isDatabaseOperationSuccessful) {
var docID = jsonObject.doctorID; // this is _id from db sent to the doctor upon logging in
console.log("jsonPssed: ", {_id : docID});
DoctorModel.findOne({_id : docID, 'appointmentList.patientID': jsonObject.appointment.patientID}, {'appointmentList.$.patientID': jsonObject.appointment.patientID},function(err, foundData) {
console.log("found data", foundData);
if(err) {
console.error("error in find doctor for adding the appointment", err);
isDatabaseOperationSuccessful(false, foundData);
return;
}
else {
// since no document matched your query, add the appointment
if (!foundData) {
DoctorModel.update(
{_id: docID},
{$push: {appointmentList: jsonObject.appointment}},
function(err, pushedData) {
if(err) {
console.error("error in adding", err);
isDatabaseOperationSuccessful(false, pushedData);
}
else {
console.log("adding successful", pushedData, "inserted: ", jsonObject.appointment);
isDatabaseOperationSuccessful(true, pushedData);
}
}
);
}
// since that appointment already exists, update it
else {
foundData.update({'_id':docID,'doctors.appointmentList.patientID' : jsonObject.appointment.patientID}, {$set: {'doctors.appointmentList.$.dateAndTime': jsonObject.appointment.dateAndTime}},
function(err, updatedData) {
if (err) {
console.error("error in updating", err);
isDatabaseOperationSuccessful(false, foundData);
}
else {
if (!updatedData) {
console.log("updating failed", updatedData);
isDatabaseOperationSuccessful(true, foundData);
}
else {
console.log("updating successful", updatedData);
isDatabaseOperationSuccessful(true, foundData);
}
}
}
);
}
}
});
}
Schema:
doctorSchema = mongoose.Schema({
name : String,
appointmentList : Array // array of jsonObjects of dates and time
});
Data that I am passing to addOrUpdateAppointment(),
{
"docID": "id assigned by mongoDB",
"appointment": {
"patientID": "id assigned by mongoDB",
"dataAndTime": "IIII"
}
}

Your code is almost correct just change foundData with DoctorModel when you want to update the data. So the code becomes:
else {
DoctorModel.update({'_id':docID, 'appointmentList.patientID' : jsonObject.appointment.patientID}, {$set: {'appointmentList.$': jsonObject.appointment}},
function(err, updatedData) {....});

Related

Stripe and back4app : Cannot read property 'id' of undefined

I'm trying to integrate payment in my app.
Here is the cloud code for Back4app :
var Stripe = require("stripe")(
"TestSecretKeyOk"
);
Parse.Cloud.define("purchaseItem", function(request, response) {
var item, order;
Parse.Promise.as().then(function() {
var itemQuery = new Parse.Query('Item');
itemQuery.equalTo('ItemName', request.params.itemName);
return itemQuery.first(null,{useMasterKey: true}).then(null, function(error) {
return Parse.Promise.error('Sorry, this item is no longer available.');
});
},{useMasterKey: true}).then(function(result) {
if (!result) {
return Parse.Promise.error('Sorry, this item is no longer available.');
} else if (result.get('quantityAvailable') <= 0) {
return Parse.Promise.error('Sorry, this item is out of stock.');
}
item = result;
item.increment('quantityAvailable', -1);
return item.save(null,{useMasterKey: true}).then(null, function(error) {
console.log('Decrementing quantity failed. Error: ' + error);
return Parse.Promise.error('An error has occurred. Your credit card was not charged.');
});
},{useMasterKey: true}).then(function(result) {
if (item.get('quantityAvailable') < 0) { // can be 0 if we took the last
return Parse.Promise.error('Sorry, this item is out of stock.');}
order = new Parse.Object("Order");
order.set('name', "azeaze"); //You can pass the client data from request.params at the begining
order.set('email', "a#gmail.com");
order.set('address', "NA");
order.set('zip', "99999");
order.set('city_state', "CA");
order.set('item', item.get('ItemName'));
order.set('fulfilled', false);
order.set('charged', false);
return order.save(null,{useMasterKey:true}).then(null, function(error) {
return Parse.Promise.error('An error has occurred. Your credit card was not charged.');
});
},{useMasterKey:true}).then(function(order) {
return Stripe.charges.create({
amount: item.get('price')*100, // It needs to convert to cents
currency: "usd",
source: request.params.cardToken,
description: "Charge for dominwong4#gmail.com"
}, function(err, charge) {
// asynchronously called
console.log(charge.id);
});
},{useMasterKey:true}).then(function(purchase) {
order.set('stripePaymentId', purchase.id);
order.set('charged', true);
order.save(null,{useMasterKey:true});
},{useMasterKey:true}).then(function() {
//your email logic
},{useMasterKey:true}).then(function() {
response.success('Success');
}, function(error) {
response.error('erreur trouvé ' + error);
});
});
Everything seems working fine :
-Stripe telling me payment is ok in their backend and no error .
But even if Parse Dashboard implement the order
StripePaymentID still null and this error raising :
TypeError: Cannot read property 'id' of undefined
So i don't understand what's not working , if you can help , i would be gratefull.
I recommend you update your Stripe Version. Just need to upload a file, with the name: "package.json" and insert the content like the structure below:
{
"dependencies": {
"stripe": "^5.8.0"
}

Modify nested object with multiple keys without replacing existing keys using Mongoose/NodeJS

Schema and model:
var schema = new mongoose.Schema({
timestamp_hour: Date,
deviceID: Number,
minutes: {
'0': {temperature: Number},
'1': {temperature: Number},
.
.
.
'59': {temperature: Number}
}
},{
collection: 'devices'
});
var model = mongoose.model('deviceData', schema);
Now in a POST request, I receive some data from an external source containing a timestamp, deviceID and temperature value.
My primary key is timestamp_hour and deviceID, so if there is an existing document in the database, I need to store the temperature value in minutes: {[minute_value]: temperature}. I currently derive minute_value from the timestamp, and I can query the database, all well and good. Now I need to update the minutes object in the document by adding the new key-value pair.
So after deriving the required values, I try running this:
var query = {timestamp_hour: timestamp, deviceID: deviceID};
var update = {minutes: {[minute]: {temperature: tempData}}};
deviceData.findOneAndUpdate(query, update, {upsert: true}, function(err, doc){
if(err) return res.send(500, {error: err});
return res.send("successfully saved");
});
Now the issue is, it replaces the entire minutes object inside document with the new single value.
Example:
Original document:
{
"deviceID" : 1,
"timestamp_hour" : ISODate("2016-10-29T08:00:00Z"),
"minutes" : { "38" : { "temperature" : 39.5 } },
}
Document after update:
{
"deviceID" : 1,
"timestamp_hour" : ISODate("2016-10-29T08:00:00Z"),
"minutes" : { "39" : { "temperature" : 38.0 } },
}
What I need:
{
"deviceID" : 1,
"timestamp_hour" : ISODate("2016-10-29T08:00:00Z"),
"minutes" : { "38" : { "temperature" : 39.5 }
"39" " { "temperature" : 38.0 } },
}
I'm new to MEAN, but I can see why my approach doesn't work since the update call just modifies the nested object.
I'd appreciate any help regarding the correct approach to use for achieving this functionality.
You can do this within a single update using a combination of the dot and bracket notations to construct the update object as follows:
var query = { "timestamp_hour": timestamp, "deviceID": deviceID },
update = { "$set": { } },
options = { "upsert": true };
update["$set"]["minutes."+ minute] = { "temperature": tempData };
deviceData.findOneAndUpdate(query, update, options, function(err, doc){
if(err) return res.send(500, {error: err});
return res.send("successfully saved");
});
Okay, so this works:
deviceData.findOne(query, function(err, doc) {
if(err) return done(err);
if(!doc){
data.save(function(err){
if(err) throw err;
res.json({"Result":"Success"});
});
} else {
doc.minutes[minute] = {temperature: tempData}
doc.save(function(err) {});
res.json(doc);
}
});

Unable to Insert Data into a collection

I have officer Schema in which if a user wants to fix an appointment, his entry is made in the DB. The schema is:
officerSchema = mongoose.Schema({
email : {type: String,
index: { unique: true }
},
appointmentList : Array // array of jsonObject of dates and userID
});
The AppointmentList is an array of JSON Objects which contains the ID of the officer with which appointment has to be made, date and userID (the user which wants to fix the appointment).
However to avoid duplicate appointment entries, I have been using several methods mentioned on the internet. None of them have worked for me so far. I am posting the code below. The problem with below code is it NEVER inserts any data in the appointmentsList. However if I use save() instead of update() insertion occurs but duplicates also get inserted.
Here is the JSON Object that I want to add in the array from DB,
{
"id": "1321231231",
"appointment": {
"userID": "31321",
"date": "24 March"
}
}
var ID = requestObject.id;
var newObject = {$addToSet: requestObject.appointment};
OfficerModel.findOne({_id : ID}, function(err, foundData) {
if(err) {
console.log(err);
return;
}
else {
var dbList = foundData.list;
dbList.push(newObject);
foundData.update(function(err, updatedData) {
if(err) {
console.log( err);
}
else {
console.log("successful");
}
});
}
});
Using the $addToSet operator might work for you.
var appt = {
id: "1321231231",
appointment: {
userID: "31321",
date: "24 March"
}
}
Officer.update(
{_id: ID},
{$addToSet: {appointmentList: appt}},
function(err) { ... }
);
But it's not a perfect solution because {one: 1, two: 2} and {two: 2, one: 1} aren't interpreted as equal, so they could both get added to an array with $addToSet.
To totally avoid duplicates, you could do something like this:
var appt = {
id: "1321231231",
appointment: {
userID: "31321",
date: "24 March"
}
};
Officer.findOne(
{_id: ID, 'appointmentList.id': appt.id},
function(err, officerDoc) {
if (err) { ... }
// since no document matched your query, add the appointment
if (!officerDoc) {
Officer.update(
{_id: ID},
{$push: {appointmentList: appt}},
function(err) { ... }
);
}
// since that appointment already exists, update it
else {
Officer.update(
{_id: ID, 'appointmentList.id': appt.id},
{$set: {'appointmentList.$.appointment': appt.appointment}},
function(err) { ... }
);
}
}
);
The operation above that updates the existing appointment uses the positional operator.

Unable to dynamically load Json Arrays from JSP to a Jstree

I was trying to make a simple LDAP client to just retrieve the data from an LDAP server. I am returning array of JSON objects from the JSP. On click of any value I will get some data from online server. I am able to load the first set of array into a tree. The arrays got in the next step dont get attached to the JSTree. My codes:
function getGroupsStructure(id) {
console.log("in getGroupsStructure-->");
var paramId = "";
if(id == '') {
console.log("in if-->");
paramId = "c=de";
} else {
console.log("in else-->");
paramId = id;
}
var params = {
"DN" : paramId,
};
console.log("params-->",params);
var getGroupsStructureForUserService = service(webURL + "sendingValues/getGroupsStructureForUser",params,"POST");
getGroupsStructureForUserService.success(function(data) {
console.log("in success-->dta-->",data);
if(data.errorCode == '0') {
console.log("in error code 0-->dta-->",data.treeData);
$('.treeNode').jstree({
'core': {
'data': function (obj, cb) {
cb.call(this,
data.treeData);
}
}
});
console.log("Tree Created...");
} else {
console.log("error code not 0--data-->",data);
}
$(document).off('click').on('click', '.treeNode a', function() {
console.log("on click of a-->");
var id = $(this).parent().attr('id');
console.log("id-->",id);
getGroupsStructure(id);
console.log("after getGroupsStructure");
});
});
getGroupsStructureForUserService.error(function(data) {
console.log(" empty error");
// console.log(err);
});
}
The JSP Code is
def NextLevelLDAP(String DN) {
// println "Next Level===>"
assert ldap!=null
def responseArray=[]
def results=ldap.search('objectClass=*',DN,SearchScope.ONE) //Will be triggered when + is pressed in GUI to get next level of tree
// assert results==null
if(DN.startsWith("c="))
{
JSONObject responseJson1=new JSONObject()
responseJson1.put("id", initialDN )
responseJson1.put("parent", "#")
responseJson1.put("text","Parent")
responseArray.add(responseJson1)
for(entry in results) {
// println entry
// println "In NextLevel Using InitialDN"
JSONObject responseJson=new JSONObject()
responseJson.put("id", entry.dn)
responseJson.put("parent", DN)
String tempResDN=entry.dn.toString()
def tempLength=tempResDN.length() - DN.length()
// println tempResDN
String tempName=tempResDN.substring(2,tempLength-1)
// println tempName
responseJson.put("text",tempName)
responseArray.add(responseJson)
// println entry
println responseJson.toString()
}
return responseArray
}
if(results.size!=0)
{
for(entry in results) {
println entry
JSONObject responseJson=new JSONObject()
responseJson.put("id", entry.dn)
responseJson.put("parent", DN)
String tempResDN=entry.dn.toString()
def tempLength=tempResDN.length() - DN.length()
// println tempResDN
String tempName=tempResDN.substring(2,tempLength-1)
println tempName
responseJson.put("text",tempName)
responseArray.add(responseJson)
// println entry
}
return responseArray
}
}
Please Ignore the way of getting the Parent ID. Its Something COmplicated.
Please help me out how do I get The tree nodes created dynamically. I am just getting the fist level of the tree. The data on click for other levels is being shown in the console but not getting attached to the tree.
Thank you.
You have it the other way around - you need to create the tree and have it make the request for you, so instead of this:
'data': function (obj, cb) {
cb.call(this, data.treeData);
}
Use something like this:
'data': function (obj, cb) {
// you probably need to pass the obj.id as a parameter to the service
// keep in mind if obj.id is "#" you need to return the root nodes
service(...).success(function (data) {
cb.call(this, data.treeData);
});
}
This way you do not need to detach and reattach click handlers every time and it will work out of the box for opening nodes. If you want to open a node on click, you can use this:
$('#tree').on('select_node.jstree', function (e, data) {
data.instance.open_node(data.node);
});
So your whole code should look something like this:
function load(id) {
var params = {
"DN" : id && id !== '#' ? id : "c=de"
};
return service(webURL + "sendingValues/getGroupsStructureForUser", params, "POST");
}
$('#tree')
.jstree({
'core' : {
'data': function (obj, cb) {
load(obj.id).success(function (data) {
cb.(data.treeData);
});
}
}
})
.on('select_node.jstree', function (e, data) {
data.instance.open_node(data.node);
});
Just make sure you mark the nodes your return as having children (set their children property to boolean true).

Using MongoJs and Node.JS to store data

I have successfully connected to MongoDb and used a form to send some data. I would now like to store the data in a json document with a collection. So my current output is:
{
"_id": "53be957007d2c838083046a6",
"subscriberinfo": "X",
"grouporpolicynumber": "X",
"title": "X",
"clientnumber": "X",
"xnumber": "X",
"postedOn": "2014-07-10T13:30:24.499Z"
}
I would like it to look like:
{
"_id": "53be957007d2c838083046a6",
"ReferenceInfo": {
"subscriberinfo": "00003",
"grouporpolicynumber": "Direct",
"title": "SNP",
"clientnumber": "VG00003M",
"HICnumber": "264134187C"
}
"postedOn": "2014-07-10T13:30:24.499Z"
}
Current code looks like this:
function postNewJob(req , res , next){
var job = {};
job.subscriberinfo = req.params.subscriberinfo;
job.grouporpolicynumber = req.params.grouporpolicynumber;
job.title = req.params.clientreportingcategory;
job.clientnumber = req.params.clientnumber;
job.HICnumber = req.params.hicnumber;
job.postedOn = new Date();
res.setHeader('Access-Control-Allow-Origin','*');
memberInfo.save(job , function(err , success){
console.log('Response success '+success);
console.log('Response error '+err);
if(success){
res.send(201 , job);
return next();
}else{
return next(err);
}
});
}
Have you tried something like this?
function postNewJob(req , res , next){
var job = {
referenceInfo: {
subscriberinfo : req.params.subscriberinfo,
grouporpolicynumber : req.params.grouporpolicynumber,
title : req.params.clientreportingcategory,
clientnumber : req.params.clientnumber,
HICnumber : req.params.hicnumber
},
postedOn: new Date();
};
res.setHeader('Access-Control-Allow-Origin','*');
memberInfo.save(job, function(err, job){
if(err) {
console.error('Response error ' + err);
next(err);
} else {
console.log('Response success ' + job);
res.send(201, job);
next(req, res);
}
});
}
On another note, I changed around your callback function that's passed in to save. Mongo will call the function, passing in error and data (data in this case being job) which allows you to conditionally log error or success depending on the status of the save. Also, because those are asynchronous functions, returning the call of next() will not actually impact the code. Also, when calling next(), it is advisable to pass along the req and res from before, so that more actions can be taken from that data.
Hope that helps!