I try remove this item from array in database on click button, but I got errors, I can't see my mistakes. I have error: RangeError: Maximum call stack size exceeded and what's more important I have /api/editProduct/undefined
factory:
userFactory.deleteDescription = function(description) {
return $http.delete('/api/editProduct/' + description)
}
api
router.delete('/editProduct/:description', function(req, res){
Product.findOneAndUpdate({ _id: req.body_id }, { $pull: { description: this }}, function(err, product){
if(err) throw err;
if(!product){
res.json({ success: false, message: 'No user found' });
} else {
console.log('ok')
}
});
});
model
var productSchema = new Schema({
title: {
type: String,
require: true,
},
level: {
type: String,
require:true,
},
description: [{
type: String,
require: true,
}],
});
The piont is remove chosen item
when you use named parameters in your expressjs routes, you can access the value via req.params['yourKey']. in your case this would be req.params.description
so for you to remove a description entry within one of your Products, you can do
Product.findOneAndUpdate(
{ _id: req.body_id },
{ $pull: { description: req.params.description }},
function(err, product){
...
}
);
Related
I am trying to update doc in mongo with node. I am doing that:
var id = data[0]._id;
var updated = {
level: mod.level,
levelName: mod.levelName,
levelType: mod.levelType,
map: mod.map,
waves: mod.waves
};
model.findByIdAndUpdate(id, updated, function(err, data){
if(err){
console.log('error');
console.log(err);
res.send(err);
} else {
console.log('update');
console.log(data);
res.send({ data: 'Record has been updated' });
}
});
The process is going to else clause, i can see 'update' log, then there is a null in next console.log and the change is not reflected in db. Is there any obvious error here? I've read documentations and it seems to be valid but somehow it just don't want to work.
This is my schema:
var Schema = mongo.Schema;
var LevelSchema = new Schema({
level: { type: String },
levelName: { type: String },
levelType: { type: String },
map: { type: Object },
waves: { type: Object }
}, { versionKey: false });
I am working in creating a todo list and one of the action I want users to do is delete all completed todos in one click. I have my models here, and the code I have, I have been reading trying to figure it out, but can't find it anywhere. Thanks in advance.
User Model
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
todos: [{
type: mongoose.Types.ObjectId,
ref: 'Todo'
}]
});
Todo model:
const TodoSchema = new mongoose.Schema({
creator: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User',
},
content: {
type: String,
required: true,
},
completed: {
type: Boolean,
default: false
},
});
This is what I have now. I get a "Cast to ObjectId failed for value true at path todos.
router.delete('/delete/completed', auth, async (req, res) => {
try {
const userTodos = await User.update(
{'_id':req.user.id},
{ $pull: { 'todos': { 'completed': true } } },
{ multi: true }
);
if (!userTodos) {
return res.status(400).send('Server error');
}
return res.json({ userTodos });
//return res.json({msg: 'All completed removed'})
} catch (err) {
console.error(err.message);
return res.status(404).json({ msg: 'Something went wrong, try again' });
}
});
If you are (as it seems from your code) using mongoose, you could use mongoose's populate feature:
const userTodos = await User.find(
{'_id':req.user.id}).populate('todos', {
match: {completed: true}
});
please note, however, that you'll need to delete both the documents in the todos collection, AND the todo reference in the user's todos array. You may consider to remove one side of the reference, see the pros and cons of two-way referencing here
I have the object array's ID and I want to update the info with information I already have on my backend.
My code deletes every array and creates a new one with the new info.
I want to access the array with the variable ID and then change it's values:
const ProdcutSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
productDescription:{
type: String,
required: true
},
pricePerUnit:{
type: Number,
required: true
},
productAmmount:{
type:Number,
required: true
},
/*productImagePath:{
type:String,
required: true
}*/
});
const UserSchema = new mongoose.Schema({
name:{
type: String,
},
email:{
type: String,
},
password:{
type: String,
},
date:{
type: Date,
default: Date.now
},
products:[ProdcutSchema]
});
//Update products
router.put('/dashboard/:id', (req, res)=>{
const ID = req.params.id;
const {product_name, price_PerUnit, product_Description, product_Ammount} = req.body; //Get access to ajax data using body parser
if(!product_name || !price_PerUnit || !product_Description || !product_Ammount){
res.send('Please fill out all fields with valid content');
}else{
User.products.findOneAndUpdate(
{ _id : ID },
{ $set: { products: {
name :product_name,
productDescription : product_Description,
pricePerUnit : price_PerUnit,
productAmmount : product_Ammount
} } },
(err) => {
if (err) throw console.log('found errors');
console.log('no errors');
})
}
});
If you have ObjectId of that item you want to update, code should look like this:
User.products.findOneAndUpdate(
{ _id: ID, "products._id": <here goes id for an array element> },
{
$set: {
"products.$": {
name: product_name,
productDescription: product_Description,
pricePerUnit: price_PerUnit,
productAmmount: product_Ammount
}
}
},
err => {
if (err) throw console.log("found errors");
console.log("no errors");
}
);
Also u gotta be aware that u need to supply an specific ID of an array element for this kind of situation when you want to update subdocument.
Node js with mongoose.
model has fields that are not selected by default queries(select:false in model). In some scenarios I need to test the result to have the field selected. I have tried sinon-mongoose but it just tells me if a populate or select method was called, but for more flexibility I need to check the result data. And a requirement is not to use any real db connection, as it is a unit test.
The model
var DoctorSchema = new Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true
},
middleName: {
type: String
},
institutionName: {
type: String,
required: true,
select: false
}
});
The Service
module.exports = function (Doctor) {
service.getById = function(req, res, next){
Doctor.findOne({"_id" : req.params.id}).select('+institutionName').exec(function (err, doc) {
if (err) {
console.log(err);
return
};
if (!doc) {
res.send(404);
}
else {
res.json(doc);
}
});
}
}
So this can be tested
describe('doctorService getById', function () {
it('presentationService should call getById', function (done) {
var DoctorMock = sinon.mock(DoctorModel);
DoctorMock
.expects('findOne').withArgs({ "_id": "123" })
.chain("select").withArgs('+institutionName')
.chain('exec')
.yields(null, seed.doctor);
var serviceMock = doctorService(DoctorModel);
var res = {
json: function (data) {
DoctorMock.verify();
DoctorMock.restore();
assert.equal(seed.doctor, data, "Test fails due to unexpected result");
done();
}
};
serviceMock.getById({param:{id:"123"}}, res);
});
});
But in my example the test is bound to the chain. My intuition tells me that this is not a good approach.
I am using mongoose and I am facing a problem of creating a document if it does not exist, and if it exists, I want to update an array in the document.
For example, if I have
var courseSchema = new mongoose.Schema({
code : { type: String },
name : { type: String },
dept : { type: String },
instructors : [{ type : mongoose.Schema.ObjectId, ref: 'User' }],
});
var Course = mongoose.model('Course', courseSchema);
...
...
// This code should check if a course exists with a specified 'code' and
// 'name' and , if it exist, I want to add req.body.instructor_id to
// instructor array in that document, else I want to create a document with
// the specified course, name(and dept) and with req.body.instructor_id as the only element in
// the instructors array
// So far I have this, but it is clearly wrong.
Course.findOneAndUpdate(
{code: req.body.code, name: req.body.name},
{$push: {instructors: req.user._id}},
{upsert: true},
function (err, course) {
if (err)
console.log("error " + err);
else {
console.log(JSON.stringify(course, null, '\t'));
}
}
);
The second parameter should be the whole object, not only instructors. For example:
function findOneAndUpdateCourse(req, callback){
Course.findOneAndUpdate(
{code: req.body.code, name: req.body.name},
{
$setOnInsert: { code: req.body.code},
$setOnInsert: { name: req.body.name},
$push: {instructors: req.user._id}}
},
{upsert: true},
function (err, course) {
if (err)
console.log("error " + err);
else {
console.log(JSON.stringify(course, null, '\t'));
}
}
);
}