I have this schema
var ArticleSchema = new Schema({
user_id: { type: Schema.ObjectId, ref: "User"},
title: String,
description: String,
content: String,
visible: Boolean,
saved: Boolean,
deleted: {type: Boolean, default: false },
permalink: String,
created_at: { type: Date, default: Date.now },
edited_at: { type: Date, default: Date.now },
tags : [],
comments: {
comment: String,
name: String,
email: String,
date: Date,
deleted: Boolean,
}
});
I want to update the deleted field into the comments array for a specific array.
Here is how I'm doing it.
this.model.update(
{
_id: data.articleId
},
{
$set: { 'comments.$.deleted' : true }
},
function(err, doc){
console.info(doc);
console.info(err);
callback(doc);
});
};
Nothing happens, I tried directly on mongo console and it works.
But not in mongoose. For any reason I got in console.info(), null and 0 as results. The document is never updated.
If I try to update other value not nested it works.
You could try the following:
this.model.update(
{
_id: data.articleId
},
{
$set: { 'comments.deleted' : true }
},
function(err, doc){
console.info(doc);
console.info(err);
callback(doc);
});
};
Your code is not working because the comments field is not an array but an embedded sub-document and the $ positional operator only identifies an element in an array to update without explicitly specifying the position of the element in the array.
Related
I'm trying to update the IsActive flag inside the function object, however, it is deeply nested inside the Companies and Factories Objects. Trying to use $ is no use, as it does not work with deeply nested subdocuments. Has anyone found a way to work with this???I expect the IsActive flag to be modified, as right now it can only be reached. I've tried:
$$
List item
Placing the $ at various points i.e. Factories.Functions.$.IsActive
-Concatenating in functionIds
{function deleteFunction(companyId, factoryId, functionId) {
return Companies.update({
"CompanyId": companyId,
"Factories.FactoryId": factoryId,
"Factories.Functions.FunctionId": functionId,
}, {"$set": {"Factories.$.Functions.IsActive": false}}
).then(function (result) {
console.log("Reached", result);
return result
}).catch(function (err) {
logger.log(err);
});
}}
let functionsSchema = new mongoose.Schema({
FunctionId: Number,
Name: String,
ADGroup: String,
IsActive: Boolean,
DateCreated: {
type: Date,
default: Date.now
},
DateModified: {
type: Date,
default: Date.now
}
});
let factorySchema = new mongoose.Schema({
FactoryId: Number,
Name: String,
ADGroup: String,
IsActive: Boolean,
DateCreated: {
type: Date,
default: Date.now
},
DateModified: {
type: Date,
default: Date.now
},
Functions: [functionsSchema]
});
let companySchema = new mongoose.Schema({
CompanyId: Number,
Name: String,
IsActive: Boolean,
DateCreated: {
type: Date,
default: Date.now
},
DateModified: {
type: Date,
default: Date.now
},
Employees: [employeeSchema],
Factories: [factorySchema]
});
This is my schema
var UserSchema = new Schema({
username: String,
email: String,
password: String,
company: String,
contact: Number,
country: String,
isLoggedIn: Boolean,
createdOn: { type: Date, default: Date.now },
ads: [{ type: Schema.Types.ObjectId, ref: 'Ad' }],
notification: {
counter: {type: Number, default: 0},
notidata: [{ itemdate: { type: Date, default: Date.now }, data: {type: String}}]
}
});
var User = module.exports = mongoose.model('User', UserSchema);
I am trying to push data into the notification.notidata.data by the following way and it seems to not be working.
User.findByIdAndUpdate(newuser.id, {
'$set': {
'notification.$.counter': '1',
'notification.$.notidata.data': 'two updated'
}
}, function(err, post) {
if (err) {
console.log(err)
} else {
console.log(post);
}
});
It seems like I am not getting how to access that sub-documented field called data.
Try the $set as:
'$set': {
'notification.counter': '1',
'notification.notidata.0.data': 'two updated'
}
I have a user model schema, a work model schema, and a critique model schema. The relationship between these schema's is a user can submit many works (like blog posts), and can comment/review (which we call critiques) other people's posts (works).
So when a user submits a critique (think of it like a review), this is my post route. I find the work by the id, then create a new critique model object, and pass that to the .create() mongoose function. All goes seemingly well until I hit the foundWork.critiques.push(createdCritique) line. the console log errors out saying:
BulkWriteError: E11000 duplicate key error collection: zapper.critiques index: username_1 dup key: { : null }
Obviously, it is saying that there are two username keys in the objects and they're conflicting with each other, but I'm not familiar enough with this to find the root of the issue and fix it in the mongoose models. The models are below. If anyone could help, that'd be greatly appreciated.
// post route for getting the review
router.post('/:id', isLoggedIn, function(req, res) {
Work.findById(req.params.id, function(err, foundWork) {
if (err) {
console.log(err);
} else {
// create a new critique
var newCritique = new Critique ({
reviewerName: {
id: req.user._id,
username: req.user.username
},
work: {
id: foundWork._id,
title: foundWork.title
},
critique : req.body.critique,
date: Date.now(),
rating: 0
});
// save new critique to db
Critique.create(newCritique, function(err, createdCritique) {
if (err) {
console.log(err)
} else {
console.log("Created critique is ");
console.log(createdCritique);
// push the new critique into array of critiques of the work
foundWork.critiques.push(createdCritique);
// save to db
foundWork.save();
}
});
}
});
User model:
var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');
var UserSchema = new mongoose.Schema({
firstname: String,
lastname: String,
username: String,
password: String,
email: String,
zip: String,
bio: {
type: String,
default: ''
},
influences: {
type: String,
default: ''
},
favBooks: {
type: String,
default: ''
},
notWriting: {
type: String,
default: ''
},
favHero: {
type: String,
default: ''
},
favVillain: {
type: String,
default: ''
},
works: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Work'
}
],
critiques: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Critique'
}
],
friends: [
{
friendId: String,
friendName : String,
friendPic: String
}
],
friendRequests: [
{
sendingFriendId: String,
sendingFriendName : String,
sendingFriendPic: String
}
],
createdDate: {
type: Date,
default: Date.now
},
lastLogin: {
type: Date,
default: Date.now
}
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
Work model:
var mongoose = require('mongoose');
var WorkSchema = new mongoose.Schema({
title: String,
genre: String,
workType: String,
length: Number,
ageRange: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
manuscriptText: String,
critiques: [
{
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Critique"
}
}
],
ratingNumber: [Number],
ratingSum: {
type: Number,
default: 0
},
date: {
type: Date,
default: Date.now
},
isPublic: {
type: Boolean,
default: true
}
});
module.exports = mongoose.model("Work", WorkSchema);
Critique model:
var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');
var CritiqueSchema = new mongoose.Schema({
reviewerName: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
work: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "Work"
},
title: String
},
critique: String,
date: {
type: Date,
default: Date.now
},
rating: [Number]
});
CritiqueSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("Critique", CritiqueSchema);
When you create a unique index in MongoDB, the default behavior is that it will index null values also.
This means if you have a document in your collection with a username of null, you can not add another one with a username of null.
What you need is a sparse index which only indexes actual values (and ignores documents with null for that field).
Check this link It shows how to create a sparse index vs "normal" one in mongoose (index: true, vs spare: true). Most of the time you would want sparse indexes.
I have a schema:
var userSchema = new Schema({
name: String,
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
admin: Boolean,
created_at: Date,
updated_at: Date
});
Let's assume I have made 100 Users using this schema.
Now I want to change the schema:
var userSchema = new Schema({
name: String,
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
admin: Boolean,
created_at: Date,
friends: [Schema.Types.ObjectId], //the new addition
updated_at: Date
});
I need all new Users to have this field. I also want all of the 100 existing Users to now have this field. How can I do this?
You can use Mongoose Model.update to update all your documents in the collection.
User.update({}, { friends: [] }, { multi: true }, function (err, raw) {
if (err) return handleError(err);
console.log('The raw response from Mongo was ', raw);
});
I don't recommend to do it in production if the collection is big, since it is a heavy operation. But in your case it should be fine.
Using the query interface in a client app or your terminal you could do:
db.users.updateMany({
$set: { "friends" : [] }
});
Here's the docs reference.
it doesn't work for me :x
Here is my code
let test = await this.client.db.users.updateMany({
$set: { "roles" : [] }
});
and the output
{ ok: 0, n: 0, nModified: 0 }
I don't know how to do, i tried a lot of things and uh it doesn't work :'(
EDIT: I found, here is my code
await this.client.db.users.updateMany({ }, [ {$set : { "roles": []} } ]);
Consider this command:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, function(err) {
...
})
versus this:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, { '$set': updateObj }, function(err) {
...
})
While developing my project, I was surprised to find out that the result of the first command is the same as the result of the second command: the updateObj is merged into the existing record in the database, even in the first case when it is supposed to replace it. Is this a bug in mongoose/mongodb or am I doing something wrong? how can I replace an object on update instead of merging it? I'm using mongoose 4.0.7.
Thanks.
==========
Update:
This is the actual WorkPlan schema definition:
workPlanSchema = mongoose.Schema({
planId: { type: String, required: true },
projectName: { type: String, required: true },
projectNumber: { type: String, required: false },
projectManagerName: { type: String, required: true },
clientPhoneNumber: { type: String, required: false },
clientEmail: { type: String, required: true },
projectEndShowDate: { type: Date, required: true },
segmentationsToDisplay: { type: [String], required: false },
areas: [
{
fatherArea: { type: mongoose.Schema.ObjectId, ref: 'Area' },
childAreas: [{ childId : { type: mongoose.Schema.ObjectId, ref: 'Area' }, status: { type: String, default: 'none' } }]
}
],
logoPositions: [
{
lat: { type: Number, required: true },
lng: { type: Number, required: true }
}
],
logoPath: { type: String, required: false },
}, { collection: 'workPlans' });
WorkPlan = mongoose.model('WorkPlan', workPlanSchema);
And this is an example of updateObj:
var updateObj = {
projectManagerName: projectManagerName,
clientEmail: clientEmail,
clientPhoneNumber: clientPhoneNumber,
segmentationsToDisplay: segmentationsToDisplay ? segmentationsToDisplay.split(',') : []
}
Therefore, when I'm NOT using the $set flag, I would expect the field projectNumber, for example, not to exist in the new record, yet I see it is still there.
Mongoose update treats all top level keys as $set operations (this is made more clear in the older docs: Mongoose 2.7.x update docs).
In order to get the behavior you want, you need to set the overwrite option to true:
WorkPlan.findOneAndUpdate({ _id: req.params.id }, updateObj, { overwrite: true }, function(err) {
...
})
See Mongoose Update documentation
In addition to the answer above:
[options.overwrite=false] «Boolean» By default, if you don't include
any update operators in doc, Mongoose will wrap doc in $set for you.
This prevents you from accidentally overwriting the document. This
option tells Mongoose to skip adding $set.
Link to docs: https://mongoosejs.com/docs/api.html#model_Model.update
This is works for me $set in Mongoose 5.10.1,
WorkPlan.where({ _id: req.params.id }).updateOne(updateObj);
Note:if you have inner object then give exact path of each key in updateObj
example:
"Document.data.age" = 19
ref: https://mongoosejs.com/docs/api.html#query_Query-set