How to update a array value in Mongoose - node.js

I want to update a array value but i am not sure about the proper method to do it ,so for i tried following method but didnt worked for me.
My model,
The children field in my model
childrens: {
type: Array,
default: ''
}
My query,
Employeehierarchy.update({ _id: employeeparent._id} ,{ $set: {"$push": { "childrens": employee._id }} })
.exec(function (err, managerparent) {});
Can anyone please provide me help.Thanks.

You can't use both $set and $push in the same update expression as nested operators.
The correct syntax for using the update operators follows:
{
<operator1>: { <field1>: <value1>, ... },
<operator2>: { <field2>: <value2>, ... },
...
}
where <operator1>, <operator2> can be from any of the update operators list specified here.
For adding a new element to the array, a single $push operator will suffice e.g. you can use the findByIdAndUpdate update method to return the modified document as
Employeehierarchy.findByIdAndUpdate(employeeparent._id,
{ "$push": { "childrens": employee._id } },
{ "new": true, "upsert": true },
function (err, managerparent) {
if (err) throw err;
console.log(managerparent);
}
);
Using your original update() method, the syntax is
Employeehierarchy.update(
{ "_id": employeeparent._id},
{ "$push": { "childrens": employee._id } },
function (err, raw) {
if (err) return handleError(err);
console.log('The raw response from Mongo was ', raw);
}
);
in which the callback function receives the arguments (err, raw) where
err is the error if any occurred
raw is the full response from Mongo
Since you want to check the modified document, I'd suggest you use the findByIdAndUpdate function since the update() method won't give you the modified document, just the full write result from mongo.
If you want to update a field in the document and add an element to an array at the same time then you can do
Employeehierarchy.findByIdAndUpdate(employeeparent._id,
{
"$set": { "name": "foo" },
"$push": { "childrens": employee._id }
}
{ "new": true, "upsert": true },
function (err, managerparent) {
if (err) throw err;
console.log(managerparent);
}
);
The above will update the name field to "foo" and add the employee id to the childrens array.

can follow this
if childrens contains string values then model can be like:
childrens: [{
type : String
}]
if childrens contains ObjectId values of another collection _id and want populate then model can be like:
childrens: [{
type : mongoose.Schema.Types.ObjectId,
ref: 'refModelName'
}]
no need to use $set just use $push to insert value in childrens array. so query can be like:
Employeehierarchy.update(
{ _id: employeeparent._id},
{"$push": { "childrens": employee._id } }
).exec(function (err, managerparent) {
//
});

This will help I guess
Employeehierarchy.findOneAndUpdate(
{ _id:employeeparent._id },
{ $set: { "childrens": employee._id }}
)

Related

Remove element from nested array mongodb

i have the following document , it has two array's , one inside the other ,
attachment array and files array inside attachment array .
i want to delete an element inside files array using this element _id . but its not working with me , i tried this code , it return
{ n: 144, nModified: 0, ok: 1 }
Invoice.update({}, {
$pull: {
"attachment":
{
"files":
{
$elemMatch:
{ _id: ObjectId("5b7937014b2a961d082de9bf") }
}
}
}
}, { multi: true })
.then(result => {
console.log("delete", result);
});
this is how the document looks like
You can try below update query in 3.6 version.
Invoice.update(
{},
{"$pull":{"attachment.$[].files":{_id:ObjectId("5b7969ac8fb15f3e5c8e844e")}}},
{"multi": true}, function (err, result) {console.log(result);
});
Use db.adminCommand( { setFeatureCompatibilityVersion: 3.6 or 4.0 depending on your version } ) if your are upgrading from old version.
For Mongodb version prior to 3.6
There is only one nested level here so you can simply use $ positional operator.
Invoice.update(
{ "attachment.files._id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") },
{ "$pull": { "attachment.$.files": { "_id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") }}},
{ "multi": true }
)
For Mongodb version 3.6 and above
If you want to update multiple elements inside attachement array then you can use $[] the all positional operator.
const mongoose = require("mongoose")
Invoice.update(
{ "attachment.files._id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") },
{ "$pull": { "attachment.$[].files": { "_id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") }}},
{ "multi": true }
)
And If you want to update single element inside the attachment array then you can use $[<identifier>] that identifies the array elements that match the arrayFilters conditions.
Suppose you want to update only an element inside attachment having _id equal to ObjectId(5b7934f54b2a961d081de9ab)
Invoice.update(
{ "attachment.files._id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") },
{ "$pull": { "attachment.$[item].files": { "_id": mongoose.Types.ObjectId("5b7937014b2a961d082de9bf") } } },
{ "arrayFilters": [{ "item._id": mongoose.Types.ObjectId("5b7934f54b2a961d081de9ab") }], "multi": true }
)

Mongoose update returns undefined

How can I update a field with new properties that is initially set to be an empty object?
For example, I have the following schema:
import mongoose from 'mongoose';
var RunSchema = mongoose.Schema(
{
runId: { type: String },
reports: {
cookieSummary: {
name: String,
path: String
}
}
}
)
export default mongoose.model('Run', RunSchema);
And I'm trying to update the following document:
{
"_id": {
"$oid": "5a0565c2537e0b5d9d08ee6b"
},
"__v": 0,
"reports": {},
"runId": "8r4LNN3fRqd3qNgdW"
}
But when I run this code, it returns undefined:
Run.findOneAndUpdate({runId: '8r4LNN3fRqd3qNgdW'},
{
$set: {'reports.cookieSummary': { 'name': 'test' }},
}, (err, doc) => { console.log(doc) })
The object notation works after adding type to fields, like this: name: { type: String }
Try to use dot notation, as you're setting just one field:
Run.findOneAndUpdate(
{ runId: '8r4LNN3fRqd3qNgdW' },
{ $set: {'reports.cookieSummary.name': 'test' } },
(err, doc) => { console.log(doc) })
According to the docs, the command you're using should work but you write it wrongly. Try like this:
Run.findOneAndUpdate(
{ runId: '8r4LNN3fRqd3qNgdW' },
{ $set: { 'reports.cookieSummary': {'name': 'test'} } },
(err, doc) => { console.log(doc) })
if it does not work, maybe mongo expect that the object matches its schema when you use the command like this. But I don't think so.
Let me know.
Your query for update a document is good only the mistake is at the end of curly braces of $set. You entered un-necessary comma at the end that is actually creating problem in this case. So I suggest you to remove it and run this :
Run.findOneAndUpdate({runId: '8r4LNN3fRqd3qNgdW'},
{
$set: {'reports.cookieSummary': { 'name': 'test' }}
}, (err, doc) => { console.log(doc) });
and then see. Rest of your query is fine.
Hope It will work for you.
Thanks.
Try using below code, it will update the document and return the updated document.
var Q = require('q');
var deferred = Q.defer();
Run.findOneAndUpdate({ runId: '8r4LNN3fRqd3qNgdW' }, { $set: { 'reports.cookieSummary.name': 'test' } }, { new: true },
(err, doc) => {
console.log(doc);
deferred.resolve(doc);
});
return deferred.promise;
I made a small change. Test this solution.
Run.findOneAndUpdate({runId: '8r4LNN3fRqd3qNgdW'},
{
$set: {"reports": {'cookieSummary':{'name': 'test'}}},
}, (err, doc) => { console.log(doc) })

How do i $set and $push in one update MongoDB?

I'm trying to $push and $set at the same time, $push is working just fine, when it comes to $set, it generates this error:
MongoError: The positional operator did not find the match needed from
the query. Unexpanded update: files.$.name
Here's the code
Course.update(
{
_id: req.body.courseId,
'files.fileUrl': { $ne: url }
},{
$push: { files: { fileUrl: url } },
$set: {'files.$.name': file.name},
}, function(err, count) {
if (err) return next(err);
console.log("Successfully saved")
});
and the ORM model, I'm using mongoose
var CourseSchema = new Schema({
files: [{
fileUrl: String,
name: { type: String, default: 'File name'}
}]
});
Any help would be appreciated. Thanks.
As the error states looks like the query used is returning no documents or returning documents having no files[].
Another reason for which it might be throwing error is that you're trying to $push & $set in the same field files and probably running into an issue similar to https://jira.mongodb.org/browse/SERVER-1050
IMHO, there is no good reason to use the same field in $push & $set, instead you can simply change
$push: { files: { fileUrl: url } },
$set: {'files.$.name': file.name},
to
$push: { files: { fileUrl: url, name: file.name } },
I have written similar kind of query for my project
Hope u could relative this to your scenario
exports.candidateRating = function(req, res) {
console.log(req.query);
console.log(req.body.RoundWiseRatings);
Profiles.update({
"name": req.query.name
}, {
$set: {
"ratings": req.body.ratings,
},
$push: {
"RoundWiseRatings": req.body.RoundWiseRatings
}
}, {
multi: true
}, function(error, profiles) {
if (error) {
}
return Profiles.find({
name: req.query.name
}, function(err, profiless) {
console.log(profiless);
if (err) {
return handleError(res, err);
}
return res.status(200).json(fnStruncturedData(profiless[0].RoundWiseRatings));
});
});};
And this worked for me :)

duplicate ID mongodb

coordinatesCollection.findOne({
"unique_id": unique_id,
}, function(err, object) {
if (object) {
coordinatesCollection.update({
"unique_id": unique_id
}, {
$push: {
coordinates: {
"coordinateX": msg.coordinatex,
"coordinateY": msg.coordinatey,
"ms_time": ms_time,
"page": msg.page,
}
}
})
} else {
coordinatesCollection.insert({
"unique_id": unique_id,
"coordinates": [{
"coordinateX": msg.coordinatex,
"coordinateY": msg.coordinatey,
"ms_time": ms_time,
"page": msg.page,
}]
})
}
});
});
The objective of this code is: If unique_id exists add coordinateX, coordinateY, ms_time and page to coordinates arrays if not exists insert unique_id and new array to coordinates.
When I saw the collection I found multiple documents with the same unique_id.
What is wrong ?
For this problem I suggest You to use instead only update function with $exists statement in query.

Issue with a simple mongo/monk findAndModify query

Just a note I am fairly new to mongo and more notably very new to using node/js.
I'm trying to write a query to insert new documents or update already existing documents in my collection.
The proposed structure of the collection is:
{ _id: xxxxxxx, ip: "xxx.xxx.xxx.xxx:xxxxxx", date: "xx-xx-xx xxxx" }
Note that my intention is a store an fixed length int for the _id rather than the internal ObjectId (is this possible/considered bad practice?). The int is guaranteed to be unique and comes from another source.
var monk = require('monk');
var db = monk('localhost:27017/cgo_schedule');
var insertDocuments = function(db, match) {
var db = db;
var collection = db.get('cgo_schedule');
collection.findAndModify(
{
"query": { "_id": match.matchId },
"update": { "$set": {
"ip": match.ip,
"date": match.date
},
"$setOnInsert": {
"_id": match.matchId,
}},
"options": { "new": true, "upsert": true }
},
function(err,doc) {
if (err) throw err;
console.log( doc );
}
);
}
This doesn't work at all however. It doesn't insert anything to the database, but it also gives no errors, so I have no idea what I'm doing wrong.
The output (for console.log (doc)) is null.
What am I doing wrong?
The Monk docs aren't much help, but according to the source code, the options object must be provided as a separate parameter.
So your call should look like this instead:
collection.findAndModify(
{
"query": { "_id": match.matchId },
"update": {
"$set": {
"ip": match.ip,
"date": match.date
}
}
},
{ "new": true, "upsert": true },
function(err,doc) {
if (err) throw err;
console.log( doc );
}
);
Note that I removed the $setOnInsert part as the _id is always included on insert with an upsert.

Resources