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 });
Related
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){
...
}
);
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 developing app using Nodejs and Mongodb and mongoose. user and Subscriptions are 2 mongoose schemas. I want to get each members expire date from subscriptions collection and include it with each of members object array. But it is not working.
var UserSchema = new Schema({
title: {
type: String
},
firstName: {
type: String
},
lastName: {
type: String
},
displayName: {
type: String
},
});
var SubscriptionSchema = new Schema({
member_id: {
type: Schema.ObjectId,
ref: 'User'
},
renewal_date: {
type: Date
},
expire_date: {
type: Date
},
amount: {
type: String
},
paid_mode: {
type: String
},
});
exports.memberlist = function(req, res) {
var expire='';
user.find({}).lean().exec(function(err, collection) {
var i;
for(i=0;i<collection.length; i++)
{
Subscriptions.find({'member_id':collection[i]._id}).lean().exec(function(err, subs){
if(subs.length > 0)
{
expire = subs[0].expire_date || '';
collection[i].expire_date = 'expire';
}
});
}
res.send(collection);
});
};
It's control flow issue. You should use something like this
var async = require('async');
// ...
exports.memberlist = function(req, res) {
var expire='';
user.find({}).lean().exec(function(err, collection) {
async.eachSeries(collection, function(item, cb){
Subscriptions.find({'member_id':item._id}).lean().exec(function(err, subs){
if(subs.length > 0)
{
expire = subs[0].expire_date || '';
collection[i].expire_date = 'expire';
cb()
}
});
}, function(){
res.send(collection);
});
});
};
Read here about node control flow, and here about async module.
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'));
}
}
);
}
var urlSchema = new Schema ( {
url : String,
visitor : [{name: String,date: Date}],
counter : Number
});
var url = mongoose.model('url',urlSchema);
var domain = blah blah;
var conditions = { url: domain };
var update = { $inc : {counter:1},
$push : { visitor: [{
name: data.username,
date: new Date()
}]
}
};
var options = {upsert: true};
url.update(conditions,update,options,function(err){
if(err){
console.log(err);
}else{
console.log('A domain successfully added to DB');
}
Currently I am using the schema and code above to make an access counter for each page.
It upserts url documents which is counting total access and holding access user info.
so far so good It's working properly.
now I want to add "counter : Number" in visitor array and when the event occurs, if the user is already in visitor array,I want to update that instead of pushing new one.
But I have no idea how to make the 'double upsert' command.
is there anyway to do that?
It may be a bit difficult even impossible perform a query that satisfy your condition. I have reproduced your scenario with following query
url.findOne({'url': 'search.php', 'visitor.name': "JohnDoe"},
function (err, visitor) {
if (visitor) {
url.update(
{
'url': 'search.php', 'visitor.name': "JohnDoe"
},
{
$inc: {'visitor.$.counter': 1, 'counter': 1}
},
function(err, result) {
if (err) {
console.log("Error occured")
} else {
console.log("Success");
}
});
} else {
var conditions = { url: 'search.php' };
var update = { $inc : {counter:1},
$push : { visitor: [{
name: data.username,
date: new Date(),
counter: 0
}]
}
};
var options = {upsert: true};
url.update(conditions,update,options,function(err){
if(err){
console.log(err);
}else{
console.log('A domain successfully added to DB');
}
});
}
}
);
Simple, insert if not exists with counter = 0, update if exists with incrementing counter by 1