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.
Related
I've been stressing around trying to fix this and I've burnt myself out. I'm calling my serverless mysql trying to get kanbans from teams. I've used this method multiple times and all were working fine but that is most likely because of they only return single item whilst this returns multiple items.
This is my code which returns empty object.
async function getKanbans(team_id){
let kanbans = [];
await sql_query(`SELECT id, sName FROM table WHERE iTeam = ?`, [team_id])
.then(result => {
result.forEach(kanban => {
// console.log(kanban);
kanbans.push({
id: kanban.id,
name: kanban.sName
});
});
})
.catch(err => {
console.log(err);
});
console.log(kanbans);
return kanbans;
}
As you can see.. I am trying to print kanbans and I do get:
[
{ id: 1, name: 'Kanban_1' },
{ id: 2, name: 'Kanban_2' }
]
of out it. Then I'm trying to return it to the item that called this function and this is how that looks like:
teams.push({
id : team.id,
sName : team.sName,
sColor : team.sColor,
aKanbans : result[0]['selectedTeam'] == team.id ? getKanbans(team.id) : null,
});
(a small snippet of something bigger)
Okay, so now when I try and look at the data response (from the frontend) I get this:
{
"success": true,
"message": "Found teams",
"teams": [
{
"id": 1,
"sName": "Team1",
"sColor": "#fcba03",
"aKanbans": {}
},
{
"id": 2,
"sName": "Team2",
"sColor": "#2200ff",
"aKanbans": null
}
]
}
aKanbans from Team1 is empty, empty object. What the **** do I do? I tried mapping it and still got an empty object. React/javascript is not my main language, I just like to learn. Any suggestions?
You are mixing async / await function with normal Promises handling.
Try to change your getKanbans code like this:
async function getKanbans(team_id) {
let kanbans = [];
try {
const result = await sql_query(
`SELECT id, sName FROM table WHERE iTeam = ?`,
[team_id]
);
result.forEach((kanban) => {
kanbans.push({
id: kanban.id,
name: kanban.sName,
});
});
} catch (err) {
console.log(err);
}
return kanbans;
}
And then populate the teams using (declare the parent async):
teams.push({
id : team.id,
sName : team.sName,
sColor : team.sColor,
aKanbans : result[0]['selectedTeam'] == team.id ? getKanbans(team.id) : null,
});
I'm building a rest api that uses Sequelize to interact with the database. A query looks like this:
function read_category(req, res) {
Category.findById(req.params.categoryId, {rejectOnEmpty: true}).then(category => {
res.json(category);
}).catch(Sequelize.EmptyResultError, function () {
res.status(404).json({message: 'No category found'});
}
).catch(function (err) {
res.send(err);
}
);
}
Now I want the category object that is returned from Sequelize and then returned to the user to include the linkto the ressource. I could do:
category.dataValues.link = config.base_url + 'categories/' + category.dataValues.id;
Which would result in:
{
"id": 1,
"name": "TestCategory 1",
"position": 1,
"createdAt": "2018-08-19T11:42:09.000Z",
"updatedAt": "2018-08-19T11:42:09.000Z",
"link": "http://localhost:3000/categories/1"
}
Since I have more routes than this one I'm wondering if there's a dynamic way to add the link property to every category. I don't want to save it in the database because the base-url might differ.
Thanks!
Better way to do it is , create a getter method :
const Category = sequelize.define( 'category' , {
....
your_fields
....
},
{
getterMethods:{
link() {
return config.base_url + 'categories/' + this.id;
}
}
});
module.exports = Category;
Then
Category.findAll(...).then(categories => {
// Now there is no need to append data manually , it will added each time when you query
console.log(categories); // <-- Check the output
})
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);
}
});
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) {....});
I'm trying to extract specific document fields from a mongodb collection (v 3.0.8 at MongoLab). The returned documents must fall within a date range. My goal is to extract specific fields from these documents. My nodejs code,
var query = {}, operator1 = {}, operator2 = {}, operator3 = {} ;
operator1.$gte = +startDate;
operator2.$lte = +endDate;
operator3.$ne = 'move';
query['xid'] = 1; // Problem here?
query['date'] = Object.assign(operator1, operator2);
query['type'] = operator3;
console.log(query);
MongoClient.connect(connection, function(err, db) {
if(err){
res.send(err);
} else {
db.collection('jbone')
.find(query)
.toArray(function(err, result){
console.log(err);
res.json(result);
});
};
});
If I opt to return all fields in the date range, the query works fine. If I select only field xid I get no results. My query object looks sensible according to the docs. console.log(err) gives:
{ xid: 1,
date: { '$gte': 20160101, '$lte': 20160107 },
type: { '$ne': 'move' } }
null
null is the err.
Can anyone help me understand what I'm doing wrong?
Or point me to another similar SO questions with an answer?
Thanks
To select the specific field could be done as below
.find(
{date: { '$gte': 20160101, '$lte': 20160107 }, type: { '$ne': 'move' }},
{ xid: 1} )
Sample codes as following.
query['date'] = Object.assign(operator1, operator2);
query['type'] = operator3;
db.collection('jbone')
.find(query, {xid: 1})
.toArray(function(err, result){
console.log(err);
res.json(result);
});