mongoose findByIdAndUpdate instead of save - node.js

I'm trying to update the value of an element inside an array of my document.
The common way of update via save works as expected, but trying to use an static method, like findByIdAndUpdate doesn't work as expected.
Here bellow I paste the code I'm currently using:
var UserSchema = new mongoose.Schema({
nickname: { type: String, trim: true},
username: { type: String, trim: true },
notifications: [{
a: {
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'x' },
x: { type: mongoose.Schema.Types.ObjectId, ref: 'y' }
},
b: {
_id: { type: mongoose.Schema.Types.ObjectId, ref: 'y' },
x: { type: mongoose.Schema.Types.ObjectId, ref: 'y' }
},
read: { type: Number, default: 0 }, // 0 - Unread, 1 - read
ts: { type: Date, default: Date.now }
}]
}, { timestamps: { createdAt: 'created_at' } });
// This works as expected
UserSchema.statics.rNSave = function (user_id, notification_id) {
var vm = this;
return new Promise(function (resolve, reject) {
vm.findById(user_id, function (err, data) {
if (err) {
reject(new Error(err));
} else {
var notifications = data.notifications, i = 0;
for (i; i < notifications.length; i += 1) {
if (data.notifications[i]._id.toString() === notification_id) {
data.notifications[i].read = 1;
data.save({ validateBeforeSave: false }, function (err, updatedData) {
if (err) {
reject(new Error(err));
} else {
resolve();
}
});
return;
}
}
return reject('Error');
}
});
});
};
// This one is not working
UserSchema.statics.rNStatic = function (user_id, notification_id) {
return this.findByIdAndUpdate({ _id: user_id, notifications: { $elemMatch: { _id: notification_id }}}, { $set: { 'notifications.$.read': 1 }}).exec();
};
Any help with this?
Thanks in advice.

Related

Node.js E11000 duplicate key error collection

I'm trying to create a reservation with node.js and express and mongoose!
This is my Schema:
let mongoose = require("mongoose");
let Schema = mongoose.Schema;
let reservationSchema = new Schema({
car: [
{
type: Schema.Types.ObjectId,
ref: "cars",
required: true,
unique: false,
},
],
client: [
{
type: Schema.Types.ObjectId,
ref: "users",
required: true,
unique: false,
},
],
request: {
type: "Date",
default: Date.now(),
},
from: {
type: "Date",
required: true,
},
days: {
type: "Number",
required: true,
},
});
let reservation = mongoose.model("Reservation", reservationSchema);
module.exports = reservation;
And this is my function that I'm using to make it work while the dates does not match
function check(reservations, newReservation) {
console.log("chegou");
return new Promise(function (resolve, reject) {
ReservationModel.find({}, function (err, reservations) {
console.log("chegou aqui lol");
console.log([reservations]);
console.log(newReservation);
if (err) reject(err);
reservations.forEach(myFunction);
function myFunction(reservations) {
console.log("Siga ze");
console.log(reservations.car);
console.log(newReservation.car);
if ((reservations.car = newReservation.car)) {
console.log("chegou ao if");
let date = reservations.from;
let days = reservations.days;
var result = new Date(date);
result.setDate(result.getDate() + days);
console.log(result);
console.log(newReservation.from);
if (newReservation.from >= result) {
console.log("devia funfar crlh");
resolve(newReservation);
} else {
console.log("Nao funfou");
}
} else {
console.log("fds nao da esta merda pqp");
}
}
});
});
}
It reaches the
if (newReservation.from >= result) {
console.log("devia funfar crlh");
resolve(newReservation);
So it should work, but when I get to the part when it is going to save to the database it gives me the error:
E11000 duplicate key error collection: rent-a-car.reservations index: car_1 dup key: { car: ObjectId('625af24b81b1edc90fdef50a') }
Saying that the car is already in use, and I have specifically in the Schema to not be unique.
What can I do?

In Mogoose i found my document with find, but using update not

I'm using nodejs and mongo (with mongooose) to build a simple aplication, but i have this little problem.
If i search my documento using a find method, i found the document (and yes, i can update in this), but if i use a update method, o cant find it. Why?
My controller method
var query = {
_id: ObjectId(req.params.runner_id)
};
Runner.find(query, function(e,o) {
console.log(o); //here i found
})
Runner.update(query, req.body, function (err, qtd) {
console.log(qtd); //here note
if (err) {
...
} else {
...
}
})
My Schema
module.exports = mongoose.model("Runner", new Schema({
cellphone: {
type: String,
require: "qual o telefone?",
unique: true,
validate: {
validator: function (v) {
var re = /^\d{11}$/;
return (v == null || v.trim().length < 1) || re.test(v);
},
message: "telefone inválido"
}
},
created_at: {
type: Date,
default: Date.now
},
advisors: [{
name: {
type: String,
require: "entre com o nome"
},
email: {
type: String,
require: "entre com o e-mail"
},
advisor: {
type: ObjectId,
require: "qual a assessoria?"
}
}]
}));
My output
with update -> { ok: 0, n: 0, nModified: 0 }
with find -> [ { _id: 5a0b99a9328fec0e4111ca52,
cellphone: '85999981114',
__v: 0,
advisors: [ [Object] ],
created_at: Wed Nov 15 2017 01:34:33 GMT+0000 (UTC) } ]
app.get('/', function(req, res){
var query = {
_id: ObjectId(req.params.id)
};
Runner.find(query, function(e,o) {
console.log(o); //here i found
})
}
app.put('/:id', function(req, res){
var Id=req.params.id;
Runner.findById(Id, function (err, qtd) {
console.log(qtd); //here qtd will found
if (err) {
...
} else {
...
}
}

Mongoose post update middleware not working

I am use "mongoose": "^4.1.2". I have try to update a matchRate field when after a document being updated. But it doesn't work either not throw an any errors.
Here is code:
list.model.js
'use strict';
var mongoose = require('bluebird').promisifyAll(require('mongoose'));
import { Schema } from 'mongoose';
var ListSchema = new Schema({
name: { type: String, required: true },
user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
emails: [],
emailColRef: String,
matchCount: Number,
totalCount: Number,
matchRate: Number,
state: {
type: String,
enum: ['pending', 'complete', 'invalid']
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
default: {
type: Boolean,
default: false
}
});
ListSchema
.virtual('count')
.get(() => this.emails.length);
ListSchema
.post('update', function() {
// this.update({},{ $set: { matchRate: this.matchCount / this.totalCount } });//Not working
//////-------------OR---------------//////
// this.matchRate=this.matchCount / this.totalCount;//Not working
console.log(this.matchCount);//undefined
console.log(this.totalCount);//undefined
console.log(this.matchRate);//undefined
});
export default mongoose.model('List', ListSchema);
list.controller.js
.....
.....
.....
var newList = {};
newList.name = name;
newList.emails = emails;
newList.emailColRef = emailColRef;
newList.state = status;
newList.matchCount = matchCount;
newList.totalCount = totalCount;
var query = { name: req.body.name };
List.update(query, newList, function(err, doc) {
// index(req, res);
if (err) {
console.log("Error in list update ", err)
return;
}
fs.unlink(req.file.path, function(err) {
if (err) {
console.log("Error in removing file", err)
return;
}
});
console.log('Update list with match status');
});

Auto increase in mongoose

I have a Model : OrderEventSchema
var OrderEventSchema = new Schema(
{
orderId: { type: String, required: true },
sequence: { type: Number },
workflowId: { type: String, required: true },
type: { type: String },
transitionId: { type: String },
placeId: { type: String },
eventType: { type: String },
payLoad: { type: Schema.Types.Mixed }
}, options
);
Handle Post save :
OrderEventSchema.post('save', function(doc) {
getNextSequence(doc.orderId)
.then(function(nextSequence) {
doc.sequence = nextSequence;
doc.save();
})
})
function getNextSequence (orderId) {
return new Promise(function(resolve, reject) {
orderEvent.findOne({
orderId : orderId
}).sort({'sequence' : -1}).limit(1).exec(function(err, doc) {
if (err) {
reject(err);
} else {
resolve(doc.sequence ? doc.sequence + 1 : 1);
}
});
})
}
Now, everything I save, it will get a infinite loop, can anyone help me, how can I increase the sequence without using another module, how can I improve this code.
Thank you so much.

Mongoose won't update sub-document

I've been banging my head against this for a few hours now and just can't seem to figure it out. I decided to use Mongo on a learning project to see how I like it. Mongoose came as the recommended way to use it, so I dove into that too. I have two schemas:
var PluginSchema = new Schema({
name: { type: String, required: true },
slug: { type: String },
description: { type: String },
created_date: { type: Date, default: Date.now },
active: { type: Boolean, default: true },
user: { type: Schema.Types.ObjectId, ref: 'User' },
versions: [PluginVersion.schema]
});
PluginSchema.methods.getLatestVersion = function(callback) {
if(this.versions.length > 0) {
this.versions.sort(function(a, b) {
if(semver.gt(a.version, b.version)) {
return 1;
} else if(semver.lt(a.version, b.version)) {
return -1;
} else {
return 0;
}
});
callback(this.versions[this.versions.length-1]);
} else {
callback(undefined);
}
};
and
var PluginVersionSchema = new Schema({
version: { type: String, required: true },
downloads: { type: Number, default: 0 },
size: { type: Number, required: true },
updatedChecks: { type: Number, default: 0 },
fileName: { type: String, required: true },
uploadedDate: { type: Date, default: Date.now }
});
The issue here is the 'versions' relationship. At some point I want to update a version of the Plugin. The thing I want to update is the updatedChecks field. Basically just updatedChecks += 1.
Plugin.findById(req.params.plugin_id)
.populate('user')
.populate('versions')
.exec(function(err, plugin) {
if(err) {
res.status(404);
res.send("Plugin not found.");
} else {
plugin.getLatestVersion(function(version) {
if(version !== undefined) {
pluginData = {
stuff: "that",
gets: "returned",
tothe: "user"
};
// This says 'Affected: 1'. As expected
PluginVersion.update({_id: version._id}, {
updatedChecks: version.updatedChecks + 1
}, function(err, affected) {
console.log("Affected: " + affected);
if(err) { res.send(err); }
res.status(200);
res.json(pluginData);
});
} else {
res.status(404);
res.send("No versions found for this plugin.");
}
});
}
});
So far, so good. However, when I try to access that version again via the Plugin schema, the updatedChecks value hasn't changed! I checked the _id value on the version I'm updating versus the version that gets pulled from the Plugin.versions field and they are they same. Do I need to remove the version from Plugin.versions and re-insert a new one with the updated value? I also tried just updating the value and calling save() but that didn't seem to work either.
I ended up getting this work by accessing the plugin version directly from the Plugin object.
var pluginIndex = false;
for(var i = 0; i < plugin.versions.length; i++) {
if(plugin.versions[i]._id === version._id) {
pluginIndex = i;
}
}
if(pluginIndex !== false) {
plugin.versions[pluginIndex].updatedChecks++;
plugin.versions[pluginIndex].markModified('updatedChecks');
plugin.versions[pluginIndex].save(function() {
plugin.markModified('versions');
plugin.save(function() {
res.status(200);
res.json(pluginData);
});
});
}
I also has a little help from: Mongoose save() not updating value in an array in database document
The problem here is, your updating query is written wrong. It must be
PluginVersion.update({
_id: version._id
}, {
$set: {
updatedChecks: version.updatedChecks + 1
}
}, function(...) {
...
});
or
PluginVersion.update({
_id: version._id
}, {
$inc: {
updatedChecks: 1
}
}, function(...) {
...
});
You can find more update operators here:
http://docs.mongodb.org/manual/reference/operator/update/

Resources