updateOne command in mongoose 5.5.11 every time I execute, I get response { "n": 0, "nModified": 0, "ok": 1 } ! what's going wrong? - mongodb

I 'm trying to update a MongoDB document by mongoose model.updateOne command, But every time I execute the command, it responds {ok:1, n:0, nModified:0}
Mongoose model :
var mongoose = require('mongoose');
var measurepropsSchema = new mongoose.Schema({
measureTitle: {
type: String,
unique: true,
required: true
},
measureDescription: {
type:String,
required:false
},
measureSymbol: {
type: String,
required:false,
}
});
var collectionName = 'measureParams'
mongoose.model('Mp', measurepropsSchema, collectionName);
router :
routerm.put('/editbyid/:id', ctrlMeasProps.edit);
Route configuration :
var routesMea = require('./api/routes/measures');
app.use('/mea', routesMea);
and finally edit function :
var Mp = mongoose.model('Mp');
module.exports.edit = function (req, res) {
var measureParams = new Mp();
console.log(req.body);
try{
measureParams.updateOne(
{ _id: req.params.id },
{
measureTitle: req.body.title,
measureDescription: req.body.description,
measureSymbol: req.body.symbol
},
(err, docu) => {
console.log(measureParams);
console.log(err);
console.log('fin');
if (err)
return res.status(500).send(err);
return res.send(docu);
}
)
}catch(e){
console.log(e);
}
};
I requested the below link,
http://localhost:3000/mea/editbyid/5ce8e8555647bf5fb1b51803
requested body is a JSON object like this :
{
"title": "sth",
"description": "It`s sth",
"symbol": "$0"
}
and it responds :
{
"n": 0,
"nModified": 0,
"ok": 1
}
Here is collection "measureParams" data:
{ "_id" : ObjectId("5ce8e8375647bf5fb1b51802"), "measureTitle" : "AAAA", "measureDescription" : "It`s AAAA", "measureSymbol" : "%$" }
{ "_id" : ObjectId("5ce8e8555647bf5fb1b51803"), "measureTitle" : "BBBB", "measureDescription" : "It`s BBBB", "measureSymbol" : "##" }
{ "_id" : ObjectId("5ce8f3b96bcf65fade7c5bcf"), "measureTitle" : "CCCC", "measureDescription" : "It`s CCCC", "measureSymbol" : "$$" }
{ "_id" : ObjectId("5ce90bb3b78b6fbd4b9781ed"), "measureTitle" : "DDDD", "measureDescription" : "It`s DDDD", "measureSymbol" : "#$" }
{ "_id" : ObjectId("5ce90ed9de934a056c00a383"), "measureSymbol" : "Or", "measureDescription" : "It`s EEEE", "measureTitle" : "EEEE", "__v" : 0 }
{ "_id" : ObjectId("5ce912bc5a52000e009b6f2e"), "measureSymbol" : "Ol", "measureDescription" : "It`s FFFF", "measureTitle" : "FFFF", "__v" : 0 }
{ "_id" : ObjectId("5ce937907d656012902702cb"), "measureTitle" : "GGGG", "measureDescription" : "It`s GGGG", "measureSymbol" : "QS", "__v" : 0 }
It should update collection by ObjectId 5ce8e8555647bf5fb1b51803 with new values mentioned in json body, but it does't.
I don't know what is the problem?
Do you have any idea?

updateOne works with model name , try to update your edit function and schema file :
update last line in schema file to this :
var Mp = module.exports = mongoose.model('Mp', measurepropsSchema, collectionName);
And Edit function should look like this:
var Mp = require('/path/to/Mp/schema/file');
module.exports.edit = function (req, res) {
console.log(req.body);
try{
Mp.updateOne(
{ _id: req.params.id },
{
measureTitle: req.body.title,
measureDescription: req.body.description,
measureSymbol: req.body.symbol
},
(err, docu) => {
console.log(err);
console.log('fin');
if (err)
return res.status(500).send(err);
return res.send(docu);
}
)
}catch(e){
console.log(e);
}
};

Related

Parent.save() not working when sub document / deeply nested document is modified

I find my document from whole collection like this:
const account = await Account.findOne({ "buildings.gateways.devices.verificationCode": code })
const buildings = account.buildings
const gateways = buildings[0].gateways;
const devices = gateways[0].devices;
const device = _.filter(devices, d => d.verificationCode === code);
now I want to change one of the property "patientLastName" and then save the whole document. I am doing as below.
device.patientLastName = lastName;
const updated = await account.save();
This simply does not change anything. I have tried many solutions given but none of them working.
not sure if I can save parent document just like that?
I have few other calls where same code works but only change for this is that this is in my post call while working ones are in put call.
My Schema:
const accountSchema = new mongoose.Schema({
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
userName: { type: String, unique: true, required: true },
companyName: { type: String, required: true },
apiKey: { type: String, unique: true, required: true },
apiCallCount: { type: Number, default: 0 },
solutionType: String,
parentCompany: String,
buildings:
[
new mongoose.Schema({
buildingName: String,
address: String,
suite: String,
floor: String,
timeZone: String,
gateways:
[
new mongoose.Schema({
gatewayName: String,
gatewayKey: { type: String, sparse: true },
suite: String,
devices: [
new mongoose.Schema({
serialNumber: { type: String, sparse: true },
area: String,
connectionStatus: Number,
gatewayKey: String,
applicationNumber: Number,
firmwareVersion: String,
needsAttention: Boolean,
verificationCode: String,
patientRiskStatus: String,
patientFirstName: String,
patientLastName: String
}, { timestamps: true })
]
}, { timestamps: true })
]
}, { timestamps: true })
]
}, { timestamps: true });
Update:
I am trying this:
it gives me error message -
"message": "Converting circular structure to JSON"
const updated = account.update(
{
"_id" : ObjectId(accountId),
"buildings.gateways.devices.verificationCode": code
},
{
"$set": {
"buildings.$.gateways.0.devices.0.patientFirstName": "name1",
"buildings.$.gateways.0.devices.0.patientLastName": "name2",
}
}
)
Your help is appreciated. Thanks
UPDATED -
complete call for your reference.
// Register User
loginRouter.post('/register', async (req, res, next) => {
try {
var { email, userName, password, firstName, lastName, role, deviceIds, code } = req.body;
console.log(req.body)
// checking if email or username already exist before registering.
const verifyEmail = await User.find({
$or: [
{ 'email': email },
{ 'userName': userName },
]
})
if (verifyEmail.length > 0) {
throw new BadRequestError('DuplicateEmailOrUserName', {
message: 'Email or Username already exists'
});
}
// finding accountId for verification code first
const account = await Account.findOne({ "buildings.gateways.devices.verificationCode": code })
//console.log(account)
if (account.length === 0) {
console.log("Invalid registration code")
throw new BadRequestError('InvalidVerificationCode', {
message: 'Invalid registration code'
});
}
var accountId = account ? account._id : null
const buildings = account.buildings
const gateways = buildings[0].gateways;
const devices = gateways[0].devices;
//console.log("devices", devices)
// finding deviceId to insert for user from that account
const device = _.filter(devices, d => d.verificationCode === code);
// console.log("device", device)
if (!deviceIds) {
deviceIds = device.map(item => item._id)
// console.log("deviceIds", deviceIds)
}
const hashedPassword = await hasher.hashPassword(password);
const newUser = new User({
accountId: accountId ? accountId : undefined,
userName: userName,
password: hashedPassword,
email: email,
firstName: firstName,
lastName: lastName,
role: role,
refreshToken: uuidv4(),
refreshTokenExpiryDate: moment().add(process.env.REFRESH_TOKEN_EXPIRY_IN_DAYS, 'days'),
deviceIds: deviceIds ? deviceIds : [],
isActive: true,
});
const newlySavedUser = await newUser.save();
const {
refreshToken,
refreshTokenExpiryDate,
password: pwd,
...userWithoutSensitiveInfo
} = newlySavedUser.toObject();
**// solutions by #SuleymanSah** <----
try {
let result = await Account.findByIdAndUpdate(
accountId,
{
$set: {
"buildings.$[building].gateways.$[gateway].devices.$[device].patientFirstName": "userName"
}
},
{
arrayFilters: [
{ "building._id": ObjectId("5d254bb179584ebcbb68b712") },
{ "gateway._id": ObjectId("5d254b64ba574040d9632ada") },
{ "device.verificationCode": "4144" }
],
new: true
}
);
if (!result) return res.status(404);
console.log(result)
//res.send(result);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
res.json(newlySavedUser);
next();
} catch (err) {
next(err);
}
});
Let me know if you need more information. Thanks
You can use the filtered positional operator $ for this.
Note that we also need to have the buildingId and gatewayId to make it work dynamically.
router.put("/account/:accountId/:buildingId/:gatewayId", async (req, res) => {
const { patientFirstName, verificationCode } = req.body;
try {
let result = await Account.findByIdAndUpdate(
req.params.accountId,
{
$set: {
"buildings.$[building].gateways.$[gateway].devices.$[device].patientFirstName": patientFirstName
}
},
{
arrayFilters: [
{ "building._id": req.params.buildingId },
{ "gateway._id": req.params.gatewayId },
{ "device.verificationCode": verificationCode }
],
new: true
}
);
if (!result) return res.status(404);
res.send(result);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
TEST
Let's have this document:
{
"_id" : ObjectId("5e0da052b4b3fe5188602e11"),
"apiCallCount" : 1,
"email" : "abc#def.net",
"password" : "123123",
"userName" : "username",
"companyName" : "companyName",
"apiKey" : "apiKey",
"solutionType" : "solutionType",
"parentCompany" : "parentCompany",
"buildings" : [
{
"_id" : ObjectId("5e0da052b4b3fe5188602e12"),
"buildingName" : "buildingName 1",
"address" : "address",
"suite" : "suite",
"floor" : "floor",
"timeZone" : "String",
"gateways" : [
{
"_id" : ObjectId("5e0da052b4b3fe5188602e13"),
"gatewayName" : "gatewayName 1",
"gatewayKey" : "gatewayKey",
"suite" : "suite",
"devices" : [
{
"_id" : ObjectId("5e0da052b4b3fe5188602e15"),
"serialNumber" : "serialNumber 1",
"area" : "area",
"connectionStatus" : 0,
"gatewayKey" : "gatewayKey",
"applicationNumber" : 11,
"firmwareVersion" : "firmwareVersion",
"needsAttention" : true,
"verificationCode" : "123456",
"patientRiskStatus" : "patientRiskStatus",
"patientFirstName" : "patientFirstName",
"patientLastName" : "patientLastName",
"createdAt" : ISODate("2020-01-02T10:48:34.287+03:00"),
"updatedAt" : ISODate("2020-01-02T10:48:34.287+03:00")
},
{
"_id" : ObjectId("5e0da052b4b3fe5188602e14"),
"serialNumber" : "serialNumber 2",
"area" : "area",
"connectionStatus" : 0,
"gatewayKey" : "gatewayKey",
"applicationNumber" : 22,
"firmwareVersion" : "firmwareVersion",
"needsAttention" : true,
"verificationCode" : "987654",
"patientRiskStatus" : "patientRiskStatus",
"patientFirstName" : "patientFirstName",
"patientLastName" : "patientLastName",
"createdAt" : ISODate("2020-01-02T10:48:34.288+03:00"),
"updatedAt" : ISODate("2020-01-02T10:48:34.288+03:00")
}
],
"createdAt" : ISODate("2020-01-02T10:48:34.288+03:00"),
"updatedAt" : ISODate("2020-01-02T10:48:34.288+03:00")
}
],
"createdAt" : ISODate("2020-01-02T10:48:34.288+03:00"),
"updatedAt" : ISODate("2020-01-02T10:48:34.288+03:00")
}
],
"createdAt" : ISODate("2020-01-02T10:48:34.289+03:00"),
"updatedAt" : ISODate("2020-01-02T10:48:34.289+03:00"),
"__v" : 0
}
To update the device patientFirstName with verificationCode 123456, we need to send a PUT request to the url http://..../account/5e0da052b4b3fe5188602e11/5e0da052b4b3fe5188602e12/5e0da052b4b3fe5188602e13
5e0da052b4b3fe5188602e11 is accountId.
5e0da052b4b3fe5188602e12 is buildingId.
5e0da052b4b3fe5188602e13 is gatewayId.
Request body:
{
"verificationCode": "123456",
"patientFirstName": "UPDATED!!!"
}
Result will be like this:
{
"apiCallCount": 1,
"_id": "5e0da052b4b3fe5188602e11",
"email": "abc#def.net",
"password": "123123",
"userName": "username",
"companyName": "companyName",
"apiKey": "apiKey",
"solutionType": "solutionType",
"parentCompany": "parentCompany",
"buildings": [
{
"gateways": [
{
"devices": [
{
"_id": "5e0da052b4b3fe5188602e15",
"serialNumber": "serialNumber 1",
"area": "area",
"connectionStatus": 0,
"gatewayKey": "gatewayKey",
"applicationNumber": 11,
"firmwareVersion": "firmwareVersion",
"needsAttention": true,
"verificationCode": "123456",
"patientRiskStatus": "patientRiskStatus",
"patientFirstName": "UPDATED!!!",
"patientLastName": "patientLastName",
"createdAt": "2020-01-02T07:48:34.287Z",
"updatedAt": "2020-01-02T07:48:34.287Z"
},
{
"_id": "5e0da052b4b3fe5188602e14",
"serialNumber": "serialNumber 2",
"area": "area",
"connectionStatus": 0,
"gatewayKey": "gatewayKey",
"applicationNumber": 22,
"firmwareVersion": "firmwareVersion",
"needsAttention": true,
"verificationCode": "987654",
"patientRiskStatus": "patientRiskStatus",
"patientFirstName": "patientFirstName",
"patientLastName": "patientLastName",
"createdAt": "2020-01-02T07:48:34.288Z",
"updatedAt": "2020-01-02T07:48:34.288Z"
}
],
"_id": "5e0da052b4b3fe5188602e13",
"gatewayName": "gatewayName 1",
"gatewayKey": "gatewayKey",
"suite": "suite",
"createdAt": "2020-01-02T07:48:34.288Z",
"updatedAt": "2020-01-02T07:48:34.288Z"
}
],
"_id": "5e0da052b4b3fe5188602e12",
"buildingName": "buildingName 1",
"address": "address",
"suite": "suite",
"floor": "floor",
"timeZone": "String",
"createdAt": "2020-01-02T07:48:34.288Z",
"updatedAt": "2020-01-02T07:48:34.288Z"
}
],
"createdAt": "2020-01-02T07:48:34.289Z",
"updatedAt": "2020-01-02T09:10:25.200Z",
"__v": 0
}
And if you always want to update in the first building's in the first gateway, you may use this:
router.put("/account/:accountId", async (req, res) => {
const { patientFirstName, verificationCode } = req.body;
try {
let result = await Account.findByIdAndUpdate(
req.params.accountId,
{
$set: {
"buildings.0.gateways.0.devices.$[device].patientFirstName": patientFirstName
}
},
{
arrayFilters: [{ "device.verificationCode": verificationCode }],
new: true
}
);
if (!result) return res.status(404);
res.send(result);
} catch (err) {
console.log(err);
res.status(500).send("Something went wrong");
}
});
Now you need to send only the accountId in the url like this: http://../account/5e0da052b4b3fe5188602e11

populate following users mongoose

Lemme take time to explain what is happening from start to finish.
Preamble:
A user a follows 10 other people. When user A logs in, an X number of posts from each of the 10 people are pulled into view.
I do not know if it is the right thing to do, and will appreciate a better way of doing it. However, I wanna give it a try, and it ain't working.
Follow Model:
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let FollowSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
followers: [{
type: Schema.Types.ObjectId,
ref: 'Card'
}],
following: [{
type: Schema.Types.ObjectId,
ref: 'Card'
}]
});
module.exports = mongoose.model('Follow', FollowSchema);
Card Model
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let CardSchema = new Schema({
title: String,
content: String,
createdById: {
type: Schema.Types.ObjectId,
ref: 'User'
},
createdBy: {
type: String
}
});
module.exports = mongoose.model('Card', CardSchema);
Follow logic
When user A follows user B, do two things:
Push the user_id of B to user A document on field 'following' (A is following B)
Push user_id of A to user B document on field 'followers' (B is followed by A)
router.post('/follow', utils.loginRequired, function(req, res) {
const user_id = req.user._id;
const follow = req.body.follow_id;
let bulk = Follow.collection.initializeUnorderedBulkOp();
bulk.find({ 'user': Types.ObjectId(user_id) }).upsert().updateOne({
$addToSet: {
following: Types.ObjectId(follow)
}
});
bulk.find({ 'user': Types.ObjectId(follow) }).upsert().updateOne({
$addToSet: {
followers: Types.ObjectId(user_id)
}
})
bulk.execute(function(err, doc) {
if (err) {
return res.json({
'state': false,
'msg': err
})
}
res.json({
'state': true,
'msg': 'Followed'
})
})
})
Actual DB values
> db.follows.find().pretty()
{
"_id" : ObjectId("59e3e27dace1f14e0a70862d"),
"user" : ObjectId("59e2194177cae833894c9956"),
"following" : [
ObjectId("59e3e618ace1f14e0a708713")
]
}
{
"_id" : ObjectId("59e3e27dace1f14e0a70862e"),
"user" : ObjectId("59e13b2dca5652efc4ca2cf5"),
"followers" : [
ObjectId("59e2194177cae833894c9956"),
ObjectId("59e13b2d27cfed535928c0e7"),
ObjectId("59e3e617149f0a3f1281e849")
]
}
{
"_id" : ObjectId("59e3e71face1f14e0a708770"),
"user" : ObjectId("59e13b2d27cfed535928c0e7"),
"following" : [
ObjectId("59e3e618ace1f14e0a708713"),
ObjectId("59e13b2dca5652efc4ca2cf5"),
ObjectId("59e21942ca5652efc4ca30ab")
]
}
{
"_id" : ObjectId("59e3e71face1f14e0a708771"),
"user" : ObjectId("59e3e618ace1f14e0a708713"),
"followers" : [
ObjectId("59e13b2d27cfed535928c0e7"),
ObjectId("59e2194177cae833894c9956")
]
}
{
"_id" : ObjectId("59e3e72bace1f14e0a708779"),
"user" : ObjectId("59e21942ca5652efc4ca30ab"),
"followers" : [
ObjectId("59e13b2d27cfed535928c0e7"),
ObjectId("59e2194177cae833894c9956"),
ObjectId("59e3e617149f0a3f1281e849")
]
}
{
"_id" : ObjectId("59f0eef155ee5a5897e1a66d"),
"user" : ObjectId("59e3e617149f0a3f1281e849"),
"following" : [
ObjectId("59e21942ca5652efc4ca30ab"),
ObjectId("59e13b2dca5652efc4ca2cf5")
]
}
>
With the above database results, this is my query:
Query
router.get('/follow/list', utils.loginRequired, function(req, res) {
const user_id = req.user._id;
Follow.findOne({ 'user': Types.ObjectId(user_id) })
.populate('following')
.exec(function(err, doc) {
if (err) {
return res.json({
'state': false,
'msg': err
})
};
console.log(doc.username);
res.json({
'state': true,
'msg': 'Follow list',
'doc': doc
})
})
});
With the above query, from my little understanding of Mongoose populate, I expect to get cards from each of the Users in the following array.
My understanding and expectations might be wrong, however with such an endgoal, is this populate approach okay? Or am I trying to solve an aggregation task with population?
UPDATE:
Thanks for the answer. Getting quite close, but still, the followingCards array contains no result. Here's the contents of my current Follow model:
> db.follows.find().pretty()
{
"_id" : ObjectId("59f24c0555ee5a5897e1b23d"),
"user" : ObjectId("59f24bda1d048d1edad4bda8"),
"following" : [
ObjectId("59f24b3a55ee5a5897e1b1ec"),
ObjectId("59f24bda55ee5a5897e1b22c")
]
}
{
"_id" : ObjectId("59f24c0555ee5a5897e1b23e"),
"user" : ObjectId("59f24b3a55ee5a5897e1b1ec"),
"followers" : [
ObjectId("59f24bda1d048d1edad4bda8")
]
}
{
"_id" : ObjectId("59f24c8855ee5a5897e1b292"),
"user" : ObjectId("59f24bda55ee5a5897e1b22c"),
"followers" : [
ObjectId("59f24bda1d048d1edad4bda8")
]
}
>
Here are all the current content I have from Card Model:
> db.cards.find().pretty()
{
"_id" : ObjectId("59f24bc01d048d1edad4bda6"),
"title" : "A day or two with Hubtel's HTTP API",
"content" : "a day or two",
"external" : "",
"slug" : "a-day-or-two-with-hubtels-http-api-df77056d",
"createdBy" : "seanmavley",
"createdById" : ObjectId("59f24b391d048d1edad4bda5"),
"createdAt" : ISODate("2017-10-26T20:55:28.293Z"),
"__v" : 0
}
{
"_id" : ObjectId("59f24c5f1d048d1edad4bda9"),
"title" : "US couple stole goods worth $1.2m from Amazon",
"content" : "for what",
"external" : "https://bbc.com",
"slug" : "us-couple-stole-goods-worth-dollar12m-from-amazon-49b0a524",
"createdBy" : "nkansahrexford",
"createdById" : ObjectId("59f24bda1d048d1edad4bda8"),
"createdAt" : ISODate("2017-10-26T20:58:07.793Z"),
"__v" : 0
}
With the Populate Virtual example from yours (#Veeram), here's the response I get:
{"state":true,"msg":"Follow list","doc":{"_id":"59f24c0555ee5a5897e1b23d","user":"59f24bda1d048d1edad4bda8","following":["59f24b3a55ee5a5897e1b1ec","59f24bda55ee5a5897e1b22c"],"followers":[],"id":"59f24c0555ee5a5897e1b23d","followingCards":[]}}
The followingCards array is empty.
Using the $lookup query on the other hand simply returns []
I'm likely missing something?
You can use either virtual populate or $lookup operator in aggregation pipeline.
Using Virtual Populate
FollowSchema.virtual('followingCards', {
ref: 'Card',
localField: 'following',
foreignField: 'createdById'
});
Follow.findOne({
'user': Types.ObjectId(user_id) })
.populate('followingCards')
.exec(function(err, doc) {
console.log(JSON.stringify(doc));
});
Using $lookup aggregation
Follow.aggregate([
{
"$match": {
"user": Types.ObjectId(user_id)
}
},
{
"$lookup": {
"from": "cards",
"localField": "following",
"foreignField": "createdById",
"as": "followingCards"
}
}
]).exec(function (err, doc) {
console.log(JSON.stringify(doc));
})
var mongoose = require('mongoose'), Schema = mongoose.Schema
var eventSchema = Schema({
title : String,
location : String,
startDate : Date,
endDate : Date
});
var personSchema = Schema({
firstname: String,
lastname: String,
email: String,
dob: Date,
city: String,
eventsAttended: [{ type: Schema.Types.ObjectId, ref: 'Event' }]
});
var Event = mongoose.model('Event', eventSchema);
var Person = mongoose.model('Person', personSchema);
To show how populate is used, first create a person object,
aaron = new Person({firstname: 'Aaron'}) and an event object,
event1 = new Event({title: 'Hackathon', location: 'foo'}):
aaron.eventsAttended.push(event1);
aaron.save(callback);
Then, when you make your query, you can populate references like this:
Person
.findOne({ firstname: 'Aaron' })
.populate('eventsAttended') .exec(function(err, person) {
if (err) return handleError(err);
console.log(person);
});
// only works if we pushed refs to person.eventsAttended
note: change Activity.find to Card.find
const { ObjectID } = require("mongodb");
// import Follow and Activity(Card) schema
const userId = req.tokenData.userId; // edit this too...
Follow.aggregate([
{
$match: {
user: ObjectID(userId)
}
}
])
.then(data => {
// console.log(data)
var dataUsers = data[0].following.map(function(item) {
return item._id;
});
// console.log(dataUsers)
Activity.find(
{ createdById: { $in: dataUsers } },
{
_id: 1,
title: 1,
content: 1,
createdBy: 1,
creatorAvatar: 1,
activityType: 1,
createdAt: 1
}
)
// .sort({createdAt:-1)
.then(posts => res.send({ posts }));
});

MongoDB putting they key into $set instead of using it for lookup?

I am trying to update a message using userID as my _id
Is splitting it up into findOne - Save - Update the best way?
//
// Find and update message
//
var messageModel = require('../models/messageModel');
var messageTable = mongoose.model('messageModel');
var messageRecord = new messageModel();
var findMessage = () => {
return new Promise((resolve, reject) => {
console.log("=====START findMessage=====")
messageTable.findOne(
{ _id: userID }
,function(err, data) {
if (err) {
reject(new Error('findMessage: ' + err))
return;
}
// Who will have this as unread?
if (userManager==true) {
messageRecord.readUser = false;
messageRecord.readManager = true;
} else {
messageRecord.readUser = true;
messageRecord.readManager = false;
}
// If message not found, then create new one
if (!data) {
console.log("=====CREATE NEW RECORD=====")
messageRecord._id = userID;
messageRecord.activityDate = Math.round(new Date().getTime()/1000);
messageRecord.messages = {
"message" : message,
"date" : Math.round(new Date().getTime()/1000),
"property" : propertyID,
"booking" : bookingID,
"manager" : userManager
}
messageRecord.save(function (err, res) {
if (err) {
reject(new Error('findMessage: ' + err));
return;
}
})
console.log("=====RESOLVE findMessage=====")
resolve();
return;
}
// If message found, then add message
console.log("=====ADD LINE TO RECORD=====")
messageTable.update (
{ _id: userID },
{
$set: {
activityDate : Math.round(new Date().getTime()/1000),
readUser : messageRecord.readUser,
readManager : messageRecord.readManager
},
$push: {
messages: {
"message" : message,
"date" : Math.round(new Date().getTime()/1000),
"property" : propertyID,
"booking" : bookingID,
"manager" : userManager
}
}
},
{ upsert: true }
).exec(function (err, res) {
if (err) {
reject(new Error('findMessage: ' + err));
return;
}
})
console.log("=====RESOLVE findMessage=====")
resolve();
return;
});
})};
Do I need to put upsert:true? (what ever that means)
Or should I use findOneAndUpdate?
And would you use findOneAndUpdate or just update? And why?
I tought it went like this:
findone
if not found then save
if found then update
UPDATE - Thanks to lascot I ended up doing this, and it works great!
// Save message
messageTable.update (
{ _id: userID },
{
$setOnInsert: {
_id: userID
},
$set: {
activityDate : Math.round(new Date().getTime()/1000),
readUser : messageRecord.readUser,
readManager : messageRecord.readManager
},
$push: {
messages: {
"message" : message,
"date" : Math.round(new Date().getTime()/1000),
"property" : propertyID,
"booking" : bookingID,
"manager" : userManager
}
}
},
{ upsert: true }
).exec(function (err, res) {
if (err) {
reject(new Error('findMessage: ' + err));
return;
}
})

update if exist insert if it doesn't exist for sub docs in mongoose

I see every relevant links for my data there is not a proper solution.
My Schema is like this:
{
"_id" : ObjectId("590aa0e68d4b23760d8d0e50"),
"updatedAt" : ISODate("2017-05-08T07:03:08.314Z"),
"createdAt" : ISODate("1987-12-31T16:00:00.000Z"),
"Avatar" : "public/image/test.pic",
"countries" : [
{
"code" : "MY",
"is_favourite" : false,
"is_visited" : true,
},
{
"code" : "CA",
"is_favourite" : true
}
]
}
I want to add a country like this:
{
"code" : "QC",
"is_favourite" : true
}
if it does exist just update it from false to true or vise versa, otherwise insert the new object.
I write code for it but it seems long story and also it is not working correctly in insert mode(get this error : The positional operator did not find the match needed from the query). I would be grateful for any helps ....
var query = {"_id":req.params._id, "countries":{$elemMatch:{code:req.body.code}}}
var update = { $set: {"countries.$.is_favourite": req.body.is_favourite}}
var option = {"upsert": true}
User.findOneAndUpdate(query,update,option, function (err, user) {
if (err) return next(err);
return res.status(201).json({
success: true,
message: 'country '+ '<'+req.body.code+'> '+ 'updated as '
+req.body.is_favourite
});
});
This is what i have tested and works perfectly as expected.
Logic is pretty clear you just need to make small changes.
updateTestTable: function (req, res, callback) {
var pushData = {
"code": "QC",
"is_favourite": true
};
console.log("INSIDE");
var objectID=new mongoose.Types.ObjectId("59119107fd4790422fcb676a");
test.findOne({"_id":objectID,"countries.code":pushData.code},function(err,data){
console.log(JSON.stringify(data));
if(data!==null){
//Update Data
console.log("HELLO");
test.findOneAndUpdate({"_id":objectID,"countries.code":pushData.code},{ $set: { "countries.$.is_favourite": false} },function(err,data){
if(data){
console.log("DATA UPDATED");
console.log(data);
}
else{
console.log("ERR",err);
}
});
}
else{
//Insert Data
test.findOneAndUpdate({"_id":objectID},{$push: {countries: pushData }},function(err,data){
if(data){
console.log("DATA INSERTED");
console.log(data);
}
});
}
});
},

on the server is not added "isAdmin" : true,

I want to ask you for help.
App running on localhost great.
but on the server is not added "isAdmin" : true, to the mongoDB. When you add admin.
Why? Where is the problem ?
localhost:
{
"_id" : ObjectId("57b174723e755f5dfe36d8b0"),
"salt" : "63855ff664682ad1e8ed77ded97ca5b92da472e9f0f7d68dcb058f35e71d38a4",
"hash" : "03da57be47c9ab1c9657ae9cd5ac3d8b63d56c808e28b51d6f5166bf27d8df99a2e6c25d809fcbd2436b5b883b4a64bd835ea588348d920346d9b3b601c965b90ff23b67687118b56a2b3e35343eb4b693131f7f51f7d1c9bdb4989364477b237f49d496505592564a5c3d88a0b559dc65e5543df06e4c22da50589e6551b69c2406db093a7ef78d31bc8bb8a5423ed4b677913642e0cd335992d222c49e5c58c3450068bd5a2e1cab82a9f73829f695b4686bc76f52c76e0b6ea4f248cb7e8663a96900e5d845773f3a4f09f7988a6ae24fbbdbb0ca7e670a51acd3f9b8c06f533b8c851c40680bd7156d00fe1407acf4879d8095591e8dce3a5379e041a90acb04edecafb38b0093e20db5dc41cd803ae70f351c9e8146d0e959d10114e586a370cd8063e47cc29367af9574e1a20d3973ab4be8d5a16b8a35d89c3534cdf745adfc65cd1d769811a421ea9654884dee289807e518b7eb7ba4c3e5f59242f98df6ccb3f09a9824e8679aec579a8c9a1498fc5819a2e1e8ab2f3cbf866f0e736e5c0b855d9d0f80b462fd50bf7ebf402530aaed84d6f7db5885098124ffa225563517c276563fd7eb3b058cb1f2472896a0b322bdd3b552229a677c45847667b952807ab873e5d2356297514c85cd4c3b3fac3bc3ac16d93033546fa9096e4b738f7eabd1c3494f902d0817b977116f612b3ee9040e0f9cab7e35543a42dc30",
"username" : "mail#gmail.com",
"displayName" : "Admin",
"isAdmin" : true,
"__v" : 0
}
server:
{
"_id" : ObjectId("57b174723e755f5dfe36d8b0"),
"salt" : "63855ff664682ad1e8ed77ded97ca5b92da472e9f0f7d68dcb058f35e71d38a4",
"hash" : "03da57be47c9ab1c9657ae9cd5ac3d8b63d56c808e28b51d6f5166bf27d8df99a2e6c25d809fcbd2436b5b883b4a64bd835ea588348d920346d9b3b601c965b90ff23b67687118b56a2b3e35343eb4b693131f7f51f7d1c9bdb4989364477b237f49d496505592564a5c3d88a0b559dc65e5543df06e4c22da50589e6551b69c2406db093a7ef78d31bc8bb8a5423ed4b677913642e0cd335992d222c49e5c58c3450068bd5a2e1cab82a9f73829f695b4686bc76f52c76e0b6ea4f248cb7e8663a96900e5d845773f3a4f09f7988a6ae24fbbdbb0ca7e670a51acd3f9b8c06f533b8c851c40680bd7156d00fe1407acf4879d8095591e8dce3a5379e041a90acb04edecafb38b0093e20db5dc41cd803ae70f351c9e8146d0e959d10114e586a370cd8063e47cc29367af9574e1a20d3973ab4be8d5a16b8a35d89c3534cdf745adfc65cd1d769811a421ea9654884dee289807e518b7eb7ba4c3e5f59242f98df6ccb3f09a9824e8679aec579a8c9a1498fc5819a2e1e8ab2f3cbf866f0e736e5c0b855d9d0f80b462fd50bf7ebf402530aaed84d6f7db5885098124ffa225563517c276563fd7eb3b058cb1f2472896a0b322bdd3b552229a677c45847667b952807ab873e5d2356297514c85cd4c3b3fac3bc3ac16d93033546fa9096e4b738f7eabd1c3494f902d0817b977116f612b3ee9040e0f9cab7e35543a42dc30",
"username" : "mail#gmail.com",
"displayName" : "Admin",
"__v" : 0
}
Model
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema({
username: String,
password: String,
displayName: String,
isAdmin: Boolean
}, {
toObject: { virtuals: true },
toJSON: { virtuals: true }
});
User.virtual("token").set(function(token) {
this._token = token;
}).get(function() { return this._token; });
User.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", User);
RegisterController
app.controller("RegisterController",
[
"$scope", "$location", "Account", "Session",
function($scope, $location, account, session) {
$scope.registerForm = {
name: undefined,
email: undefined,
password: undefined,
confirmPassword: undefined,
errorMessage: undefined
};
$scope.register = function() {
account.register($scope.registerForm.name, $scope.registerForm.email, $scope.registerForm.password, $scope.registerForm.confirmPassword)
.then(function(res) {
session.setUserData(res);
$location.path("/");
}, function(response) {
$scope.registerForm.errorMessage = response.message;
});
};
}
]);
Service session
app.factory("Session", ["$http", function ($http) {
return {
getToken: function() {
var value = sessionStorage.getItem("token");
if (value) return value;
return undefined;
},
getEmail: function() {
var value = sessionStorage.getItem("email");
if (value) return value;
return undefined;
},
getIsAdmin: function() {
var value = sessionStorage.getItem("isAdmin");
if (value) return value == "true";
return undefined;
},
setUserData: function(user) {
sessionStorage.setItem("token", user.token);
sessionStorage.setItem("email", user.username);
$http.defaults.headers.common["Authorization"] = "Bearer " + user.token;
if (user.isAdmin) {
sessionStorage.setItem("isAdmin", "true");
}
},
clear: function() {
sessionStorage.clear();
$http.defaults.headers.common["Authorization"] = undefined;
}
};
}]);