Below is the code I have tried to update the values in mongoDB but it is not working and showing an error while I am trying to update the values.
The error which is coming is :
{
"name": "MongoError",
"message": "insertDocument :: caused by :: 11000 E11000 duplicate key error index: agastyaforonewaydevelopmentstaging.deviceinfos.$_id_ dup key: { : \"355537056685953\" }",
"index": 0,
"code": 11000,
"errmsg": "insertDocument :: caused by :: 11000 E11000 duplicate key error index: agastyaforonewaydevelopmentstaging.deviceinfos.$_id_ dup key: { : \"355537056685953\" }"
}
And the code is:
// mongoose.connect('mongodb://user:password#ds031671.mongolab.com:31671/oneway', function(err) {
if (err) {
console.log('connection error', err);
} else {
console.log('connection successful');
}
});
var deviceSchema = new mongoose.Schema({
_id: {
type: String,
unique: true
},
MobileNum: Number,
Fecode: String
})
var deviceinfo = mongoose.model('deviceinfo', deviceSchema);
// Device collection close
app.get('/feature', function(req, res) {
res.render('feature.ejs', {
user: req.user
});
});
app.get('/feature', function(req, res) {
res.render('feature.ejs');
});
app.post('/feature', function(req, res) {
// if(collection.findOne({_id:req.body.Imei}))
new deviceinfo({
_id: req.body.Imei,
MobileNum: req.body.Mobile,
Fecode: req.body.fecode
}).save(function(err, drd) {
if (err) res.json(err);
else
res.render('feature.ejs');
});
});
app.get('/fupdate', function(req, res) {
res.render('upfeature.ejs');
});
app.post('/fupdate', function(req, res) {
// if(collection.findOne({_id:req.body.Imei}))
new deviceinfo({
_id: req.body.Imei,
MobileNum: req.body.Mobile,
Fecode: req.body.fecode
}).update(function(err, drd) {
if (err) res.json(err);
else
res.render('feature.ejs');
});
});
How to rectify the error?
Any help would be appreciated.
Please avoid updating document using new object model of existing _id
Instead you can update a document by passing _id as query string
app.post('/fupdate/:Imei', function(req, res) {
deviceinfo.findById(req.params.Imei, function(err, device) {
if (err)
res.send(err);
device.MobileNum = req.body.Mobile;
device.Fecode = req.body.fecode;
device.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'device updated!' });
});
});
});
Check your error, it clearly states
duplicate key error index:
Which means you are trying to duplicate an index(e.g. have it twice), and you can't have that.
I checked out your code again, and i noticed you have
app.get('/feature'
Twice. Is there any reason for that?
PS: MongoDB says you have the same ID twice, which probably means there's something wrong in your front-end(back-end seems fine), and you're sending the same value.
Edit: If you want to update a record, you have to use the update method of Mongoose. Here's what the docs have to say about it http://mongoosejs.com/docs/2.7.x/docs/updating-documents.html
Otherwise you're just trying to create a new record with the same data.
#Raja
How to change the edit button so that while clicking on that it should select the id.
The edit option I have given as a link which open a page on click.Below is the code :
<table class="table table-bordered">
<tbody>
<tr>
<td><%= drd._id %></td>
<td><%= drd.MobileNum %></td>
<td><%= drd.Fecode %></td>
<td> <a class="button" href="/fupdate"><img src="/images/edit.png" width="20" height="20"></a></td>
</tr>
</tbody>
</table>
Related
I am making a user management system where the admin can login and add user details into an array called data and render it in the form of a table.There is a front-end form for the same purpose.
The problem is, I am able to take information from the the front-end from and push it to the array but not able to render in that table.
This is my user schema:
const userSchema= new mongoose.Schema({
email: String,
password: String,
data: [{
name: String,
emailAdd: String,
phone: Number,
}]
});
This is the post route for receiving user info and storing it in the array.
app.post("/add_user",function(req,res){
const userId=req.body.id;
User.findOne({userId}, function(err, foundUser) {
if (err) {
console.log(err);
} else {
if (foundUser) {
foundUser.data.push({
name:req.body.fname,
emailAdd:req.body.emailadd,
phone:req.body.phone
});
foundUser.save(function() {
res.redirect("/database");
});
// console.log(foundUser);
}
}
});
})
This is the get route for passing the object to front end:
app.get("/database", function(req, res) {
const userId=req.body.id;
if(req.isAuthenticated()){
User.find({ _id:userId,"data": {$ne: null}}, function(err, foundUser) {
if (err) {
console.log(err);
} else {
res.render("database", { newUser: foundUser });
}
});
}else{
res.redirect("/");
}
});
There is a database.ejs page containing the table where I need to render it:
<table class="list" id="employeeList">
<thead>
<tr>
<th>Full Name</th>
<th>Email</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<%newUser.forEach(function(user){ %>
<tr>
<td><%=user.data.name%></td>
<td><%=user.data.emailAdd%></td>
<td><%=user.data.phone%></td>
</tr>
<% }); %>
</tbody>
</table>
The table still remains empty even after adding the user.
(P.S: I am using passport for encryption and mongoDB as database)
.No errors are showing up hence I don't know where I am going wrong.
Any help will be appreciated!
Edit 2
I've tried the following.
routes
// competition form details
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, competition){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
users: competition
});
});
});
// competition form details post
router.post('/dashboard/users/forms/competition-form/:id', (req, res) => {
CompetitionForm.findOneAndUpdate({ _id: req.params.id }, req.body, {upsert:true}, (err, competition) => {
if (err) {
console.log(`Error saving data: ${err}`);
return res.send('Error saving data');
}
res.redirect('/dashboard');
console.log(req.body);
});
});
input
<input type="text" class="form-control" name="schoolName" placeholder="Enter school name" value="{{competition.schoolName}}"
Still no luck.
Edit 1
So I have tested your example value="{{user.schoolName}}" with users: CompetitionForm in the route, however I get the field value from the user registration and not the CompetitionForm.
Here's what I have
user model
const express = require('express');
const mongoose = require('mongoose');
var app = express();
if (app.get('env') === 'production') {
mongoose.connect(process.env.MONGODB_URI, { useMongoClient: true });
} else {
mongoose.connect('mongodb://localhost/pol-development', { useMongoClient: true });
}
var db = mongoose.connection;
mongoose.Promise = global.Promise;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log("Connection has been established");
});
var CompetitionFormSchema = mongoose.Schema({
schoolName: String,
competitionDate: String,
competitionTime: String,
competitionVenue: String,
competitionTotalOfStudents: Number,
competitionTotalParticipated: Number,
competitionTotalPersonnel: Number,
competitionJudge1Name: String,
competitionJudge1Telephone: String,
competitionJudge1Email: String,
competitionJudge2Name: String,
competitionJudge2Telephone: String,
competitionJudge2Email: String,
competitionJudge3Name: String,
competitionJudge3Telephone: String,
competitionJudge3Email: String,
// admin fields
competitionRequiredPhotos: Boolean,
competitionRequiredCertifications: Boolean
});
var CompetitionForm = module.exports = mongoose.model('CompetitionForm', CompetitionFormSchema);
route
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, CompetitionForm){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
users: CompetitionForm
});
});
});
and for the form
<form action="/dashboard/users/forms/competition-form/{{user.id}}" method="post">
<label for="schoolName">School Name <span style="color: red">*</span></label>
<input type="text" class="form-control" name="schoolName" placeholder="Enter school name" value="{{user.schoolName}}" required>
Original
I have a competition form and a collection called competitionforms
I have the form working using the following routes
// competition form details
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, CompetitionForm){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
user_id: req.params.id
});
});
});
// competition form details post
router.post('/dashboard/users/forms/competition-form/:id', (req, res) => {
CompetitionForm.findOneAndUpdate({ _id: req.params.id }, req.body, {upsert:true}, (err, competition) => {
if (err) {
console.log(`Error saving data: ${err}`);
return res.send('Error saving data');
}
res.redirect('/dashboard');
console.log(req.body);
});
});
Now I want to pass the form data so the user can see what they have entered should they go back to the form.
The form is using the users id
<form action="/dashboard/users/forms/competition-form/{{user_id}}" method="post">
So I have tried the following
{{competitionforms.user.schoolName}},
{{competitionforms.users.schoolName}},
{{users.competitionforms.schoolName}} and
{{user.competitionforms.schoolName}}
I'm not sure what other combination I can try here.
It's impossible to give you specifics without knowing what your template looks like but that is probably for the better since it appears there is a general misunderstanding of how Express renders the form from the template.
A very simplistic explanation is res.render takes a template and replaces any instances of specially formatted text, such as {{foo}}, with the values specified by the variable object as the second argument. So if that variable object had a foo property, that value would be used.
Example #1:
Template (template.hbs):
Hi {{name}}! Is {{favoriteColor}} your favorite color?
Express App:
res.render('template.hbs', { name: 'John', favoriteColor: 'green' });
Rendered Output:
Hi John! Is green your favorite color?
Example #2:
The provided variable object can also include embedded objects too!
Template (template.hbs):
Hi {{name.first}}! Is {{favorites.color}} your favorite color?
Express App:
res.render('template.hbs', { name: { first: 'John' }, favorites: { color: 'green' }});
Rendered Output:
Hi John! Is green your favorite color?
Bringing it back to your example, assuming your template looks something like the following:
Template (dashboard/users/forms/competition-form.hbs):
<form action="/dashboard/users/forms/competition-form/{{user.id}}" method="post">
<label>School: <input type="text" name="schoolName" value="{{user.schoolName}}" /></label>
Then the updated Express code would look like:
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, competitionForm){
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
user: competitionForm
});
});
});
This assumes your document object (competitionForm) has a property of schoolName.
For further reading on using Mustache templates in Express, checkout:
http://expressjs.com/en/guide/using-template-engines.html
https://github.com/janl/mustache.js
Edit:
Based on your Edit #2:
routes
// competition form details
router.get('/dashboard/users/forms/competition-form/:id', ensureAuthenticated, (req, res) => {
CompetitionForm.find(req.params.id, function(err, competition) {
res.render('dashboard/users/forms/competition-form.hbs', {
pageTitle: 'Competition Form',
users: competition
});
});
});
input
<input type="text" class="form-control" name="schoolName" placeholder="Enter school name" value="{{users.schoolName}}"
The template object properties must match the variable object properties so they can be accessed: { pageTitle: '...', users: {...} } ==> users.schoolName
I have a little trouble: I'm just trying to insert the list of raw records into mongodb collection right after I cleaned it. But I don't receive any feedback from insert method. This is my code:
model.collection.remove((removeError, removeResult) => {
console.log('remove cb');
model.collection.insert(seeds, (insertError, insertedRecords) => {
console.log('insert cb');
});
});
Actually I wanted to do this by using the mongoose API(model is the mongoose model) but on my way of exploring this problem I figured out that the native driver don't execute this as well.
That's what I have trying to use mongoose wrappers:
model.remove({}, (err, docs) => {
if (err) {
console.log('remove error');
} else {
console.log('remove success');
model.insertMany(seeds, (insertError, insertedRecords) => {
if (insertError) {
console.log('insert error');
} else {
console.log('insert success');
}
});
}
});
When I run this script I see 'remove success' and that's all. And if I comment out the removing process then 'insert success' is displayed
My mongoose model is really simple:
const schema = new Schema({
name: {type: String, unique: true, index: true},
});
seeds variable:
export default [
{name: 'USA'},
{name: 'Germany'},
{name: 'France'}, ...
Please explain me where am I wrong or what I don't understand
UPD
I have tried this using the MongoClient and it works!
MongoClient.connect(url, function(err, db) {
const collection = db.collection('countries');
collection.deleteMany({}, (err, r) => {
console.log('delete', err);
collection.insertMany(seeds, (err, r) => {
console.log('insert', err);
db.close();
Country.find({}, function (err, res) {
console.log(res);
});
});
});
});
So problem is in the mongoose. Though actually I thought {ModelName}.collection is the native driver
To clear up your confusion, this line model.collection.remove((removeError, removeResult) is wrong.
The syntax for remove is this, db.collection.remove(
<query>,
<justOne>
)
there is no query , but here model.remove({}, (err, docs) => { you do have query({}) which means delete all.
examine this statement db.mycol.remove({'title':'MongoDB Overview'}) which is a query to find and delete any document with a title of MongoDB Overview.
Does any of this makes sense?
When I try to access /course/new I get an error [ReferenceError: next is not defined].
How and where do I define next for my faulting function?
if I just add an argument nextlike I've done in earlier models I just get more errors.
courseController:
module.exports = {
'new':function(req, res, err){
Student.findOne(req.param('takes'), function foundStudent (err, student){
if (err) return next(err);
if (!student) return next();
res.view({
student: student
});
});
},
create: function(req,res,next){
Course.create(req.params.all(), function courseCreated (err, course){
if(err) next(err);
res.json(course)
});
}
};
Course model:
module.exports = {
attributes: {
code:{
type: "string"
},
name:{
type:"string"
},
takes:{
model: 'student',
required: true
}
}
};
/course/new.ejs:
<form action="/course/create" method="post">
<h2>Create a new course for <%= student.name %></h2>
<input type="hidden" name="takes" value="<%= student.id%>"/>
<input type="text" placeholder="Course Code" name="code"><br/>
<input type="text" placeholder="Name" name="student"><br/>
<input type="submit" value="Add course"/>
</form>
Student schema:
//A student can have take many courses
module.exports = {
attributes: {
name:{
type: "string",
required: true
},
username:{
type:"string"
},
courses: {
collection: 'course',
via: 'takes'
}
}
};
The problem is here:
module.exports = {
// you had err here instead of next as last argument
'new':function(req, res, next){
Student.findOne({_id:req.param('takes')}, function foundStudent (err, student){
if (err) return next(err);
if (!student) return next();
res.view({
student: student
});
});
},
create: function(req,res,next){
Course.create(req.params.all(), function courseCreated (err, course){
if(err) next(err);
res.json(course)
});
}
};
I think you need to change the definition for the function new to:
'new':function(req, res, next){
for someone who made the same mistake as me,
I did
.get((req, res) => {
instead of
.get((req, res, next) => {
I forgot the next parameter
I solved it.
'new':function(req, res, next){
Student.findOne({id:req.param('student')}, function foundStudent (err, student){
if (err) return next(err);
if (!student) return next();
res.view({
student: student
});
});
},
The problem was with the param type also. By changing it to the student model that is actually wants to access instead of the collection takes it worked.
A special thanks to #AJS for the help.
You should pass next into the function
'new':function(req, res, **next**){
Student.findOne(req.param('takes'), function foundStudent (err, student){
if (err) return next(err);
if (!student) return next();
res.view({
student: student
});
});
},
According to the Sails documentation, the next() function is used to chain middleware together. So, your incoming request can be manipulated by middleware before reaching your controller.
I believe the correct way to implement your controller method would be:
'new':function(req, res, next){
if(!req.param.hasOwnProperty('takes')) {
res.status(400)
res.view('400', {"message":"Parameter 'takes' is required but was missing in the request"});
}
Student.findOne(req.param('takes'), function foundStudent (err, student){
if (err) {
res.status(400);
res.view('400', {"message":"Sorry, there was a problem with your request"});
if (!student){ ;
res.status(404);
res.view('404', {"message":"Sorry, there was no student found by that name or id"});
}
res.view({
student: student
});
});
},
This allows you to use proper HTTP codes in your API.
I am new to the whole mean stack. I am about to create a CRUD application. I already have the easy ones, C and R but now I want to go for D. Unfortunately, when I try to delete an entry I get a 500 error. My routes are getting called but after that nothing happens.
Html
<div ng-repeat="article in articles">
<form ng-click="deleteArticle(article)">
<button type="submit" class="btn btn-primary">Delete</button>
</form>
</div>
Angular
The part that is in my controller..
$scope.deleteArticle = function(article) {
articlesFactory.removeArticle(article) }
And the part that is getting called in a factory:
art.removeArticle = function(article) {
return $http.put('/articles/' + article._id + '/remove')
};
Routes
...
router.param('article', function(req, res, next, id) {
var query = Article.findById(id);
query.exec(function (err, article) {
if (err) { return next(err); }
if (!article) { return next(new Error("Unable to find this article.")); }
req.article = article;
return next();
});
});
...
router.put('/articles/:article/remove', function(req, res, next) {
console.log("I arrived in the routes")
req.article.remove(function(err, article) {
if (err) { return next(err); }
res.json(article);
});
});
...
Model
var ArticleSchema = new mongoose.Schema({
title: String,
content: String,
likes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
ArticleSchema.methods.remove = function(callback) {
this.remove(callback);
Should use the delete method of HTTP. And try this logic, it's from angular-fullstack controller templates (I'd recommend using it over creating your own endpoints, here's the link):
router.delete('/articles/:id/remove', function(req, res, next) {
Article.findById(req.params.id, function (err, article) {
if(err) { return next(err); }
if(!article) { return res.send(404); }
article.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(204);
});
});
});
You'll need to update this as well to use delete:
art.removeArticle = function(article) {
return $http.delete('/articles/' + article._id + '/remove')
};
I know this is an old post, but I stumbled upon it as i had the same problem, so maybe it can be useful for someone.
After trying your code and using some things of TommyMac's answer, this was my outcome and should help:
Controller:
Your controller part was ok:
$scope.deleteArticle = function(article) {
articlesFactory.removeArticle(article) }
Factory: You should use DELETE instead of PUT
It worked for me with the following function:
router.delete('/articles/:article/remove', function(req, res, next) {
req.article.remove(function(err) {
if (err) {
return next(err);
}
return res.sendStatus(204);
});
});
Model: for me, it worked without providing a "remove" function at the model (apparrently there is a default function), so remove the following snippet from your code:
ArticleSchema.methods.remove = function(callback) {
this.remove(callback);