I am trying to upload some data to my MongoDB from a Node.js script, at the moment it will upload about 5 sets of data and return this error:
MongoError: E11000 duplicate key error collection: database.customers index: _id_ dup key: { : ObjectId('5cf7a6e9b4957b3848e7cac4') }
I think this is due to some data records in my JSON being the same (specifically the process), however this isn't an issue.
I have tried to use the .createIndex() function however I am not too sure how to fully integrate that with my .insertOne() function.
data= {
'Process': varprocess,
'Number' : idnumber,
}
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydatabase");
dbo.collection("customers").insertOne(data, function(err, res) {
if (err) throw err;
console.log("1 document inserted");
db.close();
});
});
{
"data": [
{
"Process": "Process1",
"Number": "00000",
},
{
"Process": "Process1",
"Number": "00001",
}
]
}
I am expecting it to upload data regardless of duplicates, as you can see it doesn't like 'Process1' being entered more than once. What can I do so that all of my data is sent to the DB without errors?
thanks
Related
Why is a successful update response always passed as an error. is something wrong with my code or is it the Mongo DB response.
However I don't see any errors when I check them on MongoDB.
MongoDB Enterprise > db.getLastError();
null
Response:
{
"lastErrorObject": {
"n": 1,
"updatedExisting": true
},
"value": {
"_id": "1111111111",
"xyz": "hgfjdfjk"
}
}
Code Block
{
try {
const db = client.db(dbName);
db.collection(cName).updateOne({ _id: id }, { $pull: query }).then((err, result) => {
if (err) {
callBack(err);
} else {
callBack(null, result);
}
});
client.close();
}
catch (err) {
callBack({
error: 'Unable to process the request',
errorMessage: err
})
}
}
getLastError() returns the server response to the current operation within that connection, and is not related to an actual error in MongoDB. It is part of MongoDB's wire protocol.
See getLastError for more details.
So I am trying to update the field status in my Report document and in my Station.reports sub-document which is an array of objects, in one single API call. The issue is that I am able to update the Report document, but not the station document when making the API call. After the call, the console.log(station.reports); returns the expected subdocument which is : [{"_id":"588fed278b50cd180bd6cc15","date":"2017-01-31T01:48:57.487Z","status":"Archived"}] But this is not saved in the corresponding Station document in my DB. Please I need help here. Thanks.
Station Document:
{
"_id": "588a777d4e26720e7afa7e1e",
"phone": "(007) – 007 – 7007",
"name": "name1",
"email": "name1#email.com",
"reports": [
{
"status": "Submitted",
"date": "2014-01-31T01:48:57.487Z",
"_id": "588fed278b50cd180bd6cc15"
}
]
}
Report Document
{
"_id": "588fed278b50cd180bd6cc15",
"description": "Description of the report",
"time": "05:48 PM",
"date": "2017-01-31T01:48:57.487Z",
"status": "Archived",
"location" : "123 Main Street"
"station" : "588a777d4e26720e7afa7e1e"
}
API Call
router.put('/reports/:id/updateStatus', function (req, res) {
Report.findById(req.params.id, function(err,report){
// if there is an error retrieving, send the error.
// nothing after res.send(err) will execute
if (err)
return res.send(err);
// Update the Report object
report.status = req.body.status;
// Update the Corresponding station.reports subdocument
Station.findOne({_id:report.station}, function (err, data) {
if(err) return console.log(err);
data.reports.forEach(function(rpt){
if (rpt._id == req.params.id){
rpt.status = req.body.status
data.save(function (err, station) {
if (err)
return res.send(err);
console.log(station.reports);
})
}
})
})
report.save(function (err, report) {
if (err)
return res.send(err);
res.json(report);
})
});
})
You are doing mistake while updating the station object. Use findOneAndUpdate to find the matching Station document, and then change the status of the matched reports item(matched using reports._id).
Try this:
Station.findOneAndUpdate({
_id:report.station,"reports._id":req.params.id
},{
$set : {reports.$.status : req.body.status}
},function(err){
if(err)
return res.send(err);
});
report._id will find the array element whose _id is req.params.id and report.$.status will update only the matching element of the array.
For more information on positional $(update) operator, Read mongoDB positional Documentation.
Also, i would suggest to save the report object in the callback of update. As nodejs is asynchronous, it will not wait for the update to finish, if you are saving report outside of the callback. And, you might get Cant set the headers after they are sent error. Thus, its recommended to do it in the callback.
Thus your final API code would look like:
router.put('/reports/:id/updateStatus', function (req, res) {
Report.findById(req.params.id, function(err,report){
// if there is an error retrieving, send the error.
// nothing after res.send(err) will execute
if (err)
return res.send(err);
// Update the Report object
report.status = req.body.status;
// Update the Corresponding station.reports subdocument
Station.findOneAndUpdate({
"_id":report.station,"reports._id":req.params.id
},{
$set : {"reports.$.status" : req.body.status}
},function(err, result){
if(err)
return res.send(err);
console.log(result);
report.save(function (err, report) {
if (err)
return res.send(err);
res.json(report);
});
});
});
})
UPDATE
Alternate Method
Another way can be, You can proceed in the original way, but don't save the data inside the forEach, instead save the data sheet forEach finishes.
Station.findOne({_id:report.station}, function (err, data) {
if(err) return console.log(err);
data.reports.forEach(function(rpt){
if (rpt._id == req.params.id){
rpt.status = req.body.status
}
});
data.save(function (err, station) {
if (err)
return res.send(err);
console.log(station.reports);
report.save(function (err, report) {
if (err)
return res.send(err);
res.json(report);
});
})
})
Hope this helps!
After multiple attempts, and with the help of Ravi, I was able to figure out a solution that worked for me pretty well. The only thing that changed was my API call. The rest of the code was unchanged.
Hope this helps someone having similar needs.
API CALL
router.put('/reports/:id/updateStatus', function (req, res) {
Report.findById(req.params.id, function(err,report){
// if there is an error retrieving, send the error.
// nothing after res.send(err) will execute
if (err)
return res.send(err);
// Update the Report object
report.status = req.body.status;
// Update the Corresponding station.reports subdocument
Station.findOne({_id:report.station}, function (err, info) {
if(err) return console.log(err);
info.reports.forEach(function(rpt){
if (rpt._id == req.params.id){
Station.update({_id:info._id, "reports._id":rpt._id },
{
$set:{"reports.$.status": req.body.status }
},function (err, results) {
if(err) return console.log("This Station couldn't be updated " + err);
console.log(results)
}
)
}
})
report.save(function (err, report) {
if (err)
return res.send(err);
res.json({report:report, station:info});
});
})
});
})
var json2csv = require('json2csv');
json2csv({data: someJSONData, fields: ['screen_name', 'statuses_count', 'location']}, function(err,csv) {
if (err) console.log(err);
console.log(csv);
});
var json = [
{
"screen_name: "Doug_E_Stile"",
"statuses_count": 1546,
"location": "Maryland""
}, {
"screen_name": "cthxidm",,
"statuses_count": 339,
"location": "peru manyas¿",
}, {
"screen_name": ""jiiiiimarjoh",
"statuses_count": 4205,,
"location": "South Cotabato, Philippines"
}
];
json2csv({data: json, fields: ['screen_name', 'statuses_count', 'location']}, function(err, excel) {
if (err) console.log(err);
fs.writeFile('file.csv', csv, function(err) {
if (err) throw err;
console.log('file saved');
});
});
i wrote the code to convert the json into the csv but it not working me can anybody help me .it will be great help[ for me
Looks like you are using a variable named csv, but the name of your function parameter is excel. It should be:
fs.writeFile('file.csv', excel, function(err) {
instead of
fs.writeFile('file.csv', csv, function(err) {
I have an application where I need to read from two different collections in my Mongo database and pass both the returned objects into a handlebars template.
With the code I have below I can't figure out how to get it to work, as the universityData and courseData variables aren't getting populated, not sure if this is the right way to do it anyway.
The university and course objects in the callbacks are working correctly as when I log I get the values I need.
router.get('/newcastle/G400', function(req, res) {
var db = req.db;
var universityData;
var courseData;
db.collection('universities', function(err, collection) {
collection.findOne({'code': 'N21'}, function(err, university) {
universityData = university;
console.log(university);
//res.render('course', {title: university.name, university: university, course: { "code": "G400", "name": "Computer Science", "studylength": "3 years (BSc)/4 years (MSc)", "requirements": "AAB - ABB", "satisfactionrating": "98"}});
});
});
db.collection('courses', function(err, collection) {
collection.findOne({'universitycode': 'N21', 'code': 'G400'}, function(err, course) {
courseData = course;
console.log(course);
});
});
console.log(universityData);
console.log(courseData);
res.render('course', {university: universityData, course: courseData});
});
My question is how can I get the objects from each of the queries to be passed into one template?
Any help would be appreciated as I'm fairly new to Javascript, node and Mongo.
Even though it's just "two" functions, you could use a module like async to help organize them without deeply nesting. Example:
var async = require('async');
// ...
router.get('/newcastle/G400', function(req, res) {
var db = req.db;
async.parallel([
universityData: function(callback) {
db.collection('universities', function(err, collection) {
if (err)
return callback(err);
collection.findOne({'code': 'N21'}, callback);
});
},
courseData: function(callback) {
db.collection('courses', function(err, collection) {
if (err)
return callback(err);
collection.findOne({'universitycode': 'N21', 'code': 'G400'}, callback);
});
}
], function(err, results) {
if (err)
return res.send(500);
// results === { universityData: { ... }, courseData: { ... } }
res.render('course', results);
});
});
I have a Node.js app that is updating data in a MongoDB database using Mongoose.
I have setup the Mongoose model and I am able to successfully use the model.find, and model.remove functions, but I can't get the model.update function to work.
Can anyone help me?
/* ------------------------ Finding/Querying works ----------------------
Flot.find({ "label": "Trips Per Day"}, function (err, docs) {
res.jsonp(docs || err);
});
*/
/* ------------------------ Removing works -----------------------
Flot.remove({ "label": "Trips Per Client" }, function (err) {
if (err) return handleError(err);
res.json(err || "removed");
});
*/
var conditions = { "label": "Average Tons per Delivery" };
var update = { "label": "Average Tons per Delivery 2" };
var options = { };
var callback = function callback(err, numberAffected, rawResponse) {
if (err) return handleError(err);
console.log('Error: ', err);
console.log('NumberAffected: ', numberAffected);
console.log('RawResponse: ', rawResponse);
res.json(err || rawResponse || numberAffected );
};
Gage.update( conditions, update, options, callback );
I was able to get this working with node-mongodb-native. I'm still not sure why Mongoose wasn't working, but at least I got something to work.
var query = {"label": "Average Tons per Delivery"};
var update = {"type": "vertical"};
var options = {};
MongoClient.connect('mongodb://localhost/db', function(err, db) {
if(err) throw err;
db.collection('justgage').findAndModify(
query,
[['_id','asc']],
{$set: update},
options,
function(err, object) {
res.jsonp("Ok");
});
});