an array in both, only it works I join the other not. I work this way. there any way to fix this inconvenience?
collection:findAndModify({
query: {
$in: [req.user._id, idunique]
},
update: {
$push: {
Amigos: {
usuario: idUserAccept,
name: fotoUserAccept,
img: fotoUserAccept
}
}
},
new: true
}).success(function(doc){
res.json(doc);
}).error(function(err){
console.log(err);
});
seem that you have mistake about query syntax.
findAndModify is Deprecated. Use findOneAndUpdate instead
check document in here
Related
I have the following query being executed:
const myData = await this.findOneAndUpdate({
myId,
color,
}, {
$setOnInsert: {
myId,
color,
date: now.format('YYYY-MM-DD'),
counter: myObj.counter - amount,
},
$inc: {
counter: -amount
},
}, {
new: true,
upsert: true,
});
I get the error:
"Updating the path 'count' would create a conflict at 'count'"
First I thought the error was happening because of the version of mongoose, but I don't think that is the case.
Now I understand this is happening because I have color in both $setOnInsert and $inc, but I don't understand why.
Also: This code works on MongoDB 3.4.24 Community but does NOT WORK on MongoDB 5.0.11 Community
So my questions are:
why this error is happening exactly? Could this be a BUG?
Why this works in older version of MongoDB?
What would be the best approach to refactor this?
You are getting the above error from MongoDB, because of the way $inc works, with upsert: true, new: true, $inc will insert a new document. Check this playground.
In your case, you have $setOnInsert and $inc, in case your matching document is not found, both the operators will try to set the value of key counter, which will create a conflict, hence you see the error. To fix it, you can use the pipeline form of updates, something like this:
const myData = await this.findOneAndUpdate({
myId,
color,
}, [
{
$set: {
myId,
color,
date: {
$cond: {
if: {$eq: ["$$ROOT", null]},
then: now.format('YYYY-MM-DD'),
else: "$$ROOT.date"
}
},
counter: {
$cond: {
if: {$eq: ["$$ROOT", null]},
then: myObj.counter - amount,
else: {$substract: ["$$ROOT.counter", amount]}
}
}
}
}
], {
new: true,
upsert: true,
});
const result = await Property.findOneAndUpdate(
{ _id: req.body._id },
{
$set: body,
$push: { property_photos: { $each: img } },
},
{
new: true
}
).populate({
path: "posted_by",
select: { email: 1 }
});
Currently, I am getting an error "Updating the path 'property_photos' would create a conflict at 'property_photos'".
But, When I am using these standalone both are working fine.
And I don't want to use updateOne because I want updated document too in my response.
So, How can I use both $set and $push with findOneAndUpdate?
Issue resolved. I was passing "property_photos" in my body object also. So it was conflicting.
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 :)
I have the following mongoose schema:
{
name: String,
subArray: [
{
subName: String,
subNumber: Number
}
]
}
I've added objects to the subArray, which get automatically assigned an "_id". In Node.js, how do I find an object by "_id" within the subArray and remove it?
You can se mongoose findOneAndUpdate along with $pull operator. So something like following would work (untested):
Model.findOneAndUpdate( {'subArray._id' : '55a19992474e7ded6b4ae2b0'} ,
{
$pull: { subArray: { _id: '55a19992474e7ded6b4ae2b0' }}
}
{new: true},
function(err, doc){
console.log(err,doc)
})
A small correction for the above code sefgment
ProductContact.findOneAndUpdate({'productRoles._id':req.params.product_role_id},
{
$pull: { productRoles: {_id:req.params.product_role_id }}
},{new:true},
function(err, productcontact) {
if(err)
res.send(err);res.json({message: 'Role successfully deleted.'});
})
I'm trying to pop and retrieve an element out of an array stored in a document. I can't use $pop since it doesn't return the POPed element. I'm trying to use findAndModify() instead. It works in the shell console, but I'm having troubles getting it to work using the mongodb node.js driver (https://www.npmjs.org/package/mongodb).
my document structure looks like so:
{ _id: '1', queue: [1,2,3]}
In mongo shell, I do:
> db.collection.findAndModify({ query: { _id: 1 },
update: { $pop: { queue: -1 } },
fields: { queue: { $slice: 1 } }, new: false })
$slice ensures that the returning document shows the element that has just been poped. To clarify, I'm not interested in what is in the queue, I'm only interested in what I have just popped out of the queue.
returns:
< {_id: 1, "queue": [1]} // yes, it works!
Using the mongodb library, I don't know how to specify the $slice: 1, it doesn't seem to be supported in the options(?):
> db.collection('collection').findAndModify(
{ _id: 1 },
[],
{ $pop: { queue: -1 }, queue: { $slice: 1 } },
{ new: false },
function(error, results) {
if(error) {
console.log(error);
}
console.log(results);
}
);
returns:
< MongoError: exception: Field name duplication not allowed with modifiers
Basically - where should I put the "queue: {$slice: 1}" part in the nodejs query to make this work? Is it even supported in the node.js driver implementation?
Also, it doesn't seem like findAndModify() is meant to be used this way. If $pop was returning the POPed value, it would be ideal. Any suggestions on how to do this?
Thanks,
- Samir
It seems like that the node.js implementation does not support the 'fields' operand at all.
We've figured out this work around:
1) We store each element in it's own document, instead of an array within the same document.
2) Now findAndModify works like so:
db.collection('collection').findAndModify(
{}, // findAndModify will match it to the first document, if multiple docs are found
[],
{},
{remove: true, new: false }, // returns & removes document from collection
function(error, results) {
if(error) {
console.log(error);
}
console.log(results);
}
);
Some good links that helped us and might help you if you have a similar issue:
https://blog.serverdensity.com/queueing-mongodb-using-mongodb/
http://www.slideshare.net/mongodb/mongodb-as-message-queue