ARRAY FILTERS in mongooDB - arrays

I have the following schema
{
"_id" : ObjectId("5ec0471dfec11a07d80c9d07"),
"name" : "jasper",
"post" : [
{
"_id" : ObjectId("5ec0473ffec11a07d80c9d08"),
"content" : "It,s all about........",
"title" : "THE NEEDY"
},
{
"_id" : ObjectId("5ec0475afec11a07d80c9d09"),
"content" : "I know..........",
"title" : "The world"
}
],
"__v" : 2
}
I want to update the content part in a particular post. I am using mongoose.
I tried the below query.Though it isn't showing any error it isn't updating in the data in the database.
var id="5ec0471dfec11a07d80c9d07";
var subid="5ec0473ffec11a07d80c9d08";
data.updateOne(
{'_id.post._id':subid},
{
$set:{
"$[post].post.$[rely].content":'ohkkk'
}
},
{arrayFilters:[{"post._id":id},{"rely._id":subid}],new:true}
);
Can you please help me find the error?

If you wanted to use arrayFilters, please try the code below:
data.updateOne({_id: id},
{
"$set": {[`post.$[inner].content`]: 'ohkkk'}
},
{
"arrayFilters": [{ "inner._id": subid }],
new: true
},
function(err, post) {
if (!err) {
res.send(post)
}
})
Alternatively, since it is 1 level nested array you could do:
data.updateOne({ _id: id, "post._id": subid }, { $set: { "post.$.content": 'ohkkk' }, { new: true } })
Hope it helps.

Related

Update documents nested multiple levels in an array

I have this JSON structure in MongoDb and want to update changing a specific value of a particular item in a nested array. I would like to change the key targetAreaId from USER_MESSAGE to VISUAL_MESSAGE.
{
"_id" : "5cde9f482f2d5b924f492da2",
"scenario" : "SCENARIOX",
"mediaType" : "VISUAL",
"opCon" : "NORMAL",
"stepConfigs" : [
{
"stepType" : "STEPX",
"enabled" : true,
"configs" : [
{
"contentTemplateId" : "5cde9f472f2d5b924f492973",
"scope" : "STANDARD",
"key" : "CONTENT"
},
{
"priorityId" : "5cde9f472f2d5b924f49224f",
"scope" : "STANDARD",
"key" : "PRIORITY"
},
{
"targetAreaId" : "USER_MESSAGE",
"scope" : "STANDARD",
"key" : "TARGET_AREA"
}
],
"description" : "XPTO"
}
],
"scope" : "STANDARD" }
How can I do it in the same time?
EDIT
I am trying this way:
var cursor = db.getCollection('CollectionX').find({
"scenario": "SCENARIOX",
"stepConfigs.stepType": "STEPX",
"stepConfigs.configs.key": "TARGET_AREA"
});
if (cursor.hasNext()) {
var doc = cursor.next();
doc.stepConfigs.find(function(v,i) {
if (v.stepType == "STEPX") {
doc.stepConfigs[i].configs.find(function(w,j) {
if (w.key == "TARGET_AREA") {
var result = db.getCollection('CollectionX').update(
{ "_id" : doc._id },
{ "$set" : { doc.stepConfigs[i].configs[j].targetAreaId: "VISUAL_MESSAGE" }}
);
}
});
};
});
} else {
print("Step does not exist");
}
But the error below is occurring:
Error: Line 15: Unexpected token .
I don't think that's possible.
You can update the specific element you want using this query:
db.test_array.updateOne({}, {
$set: {
"stepConfigs.$[firstArray].configs.$[secondArray].targetAreaId": "VISUAL_MESSAGE"
}
}, {
arrayFilters: [{
"firstArray.stepType": "STEPX"
}, {
"secondArray.targetAreaId": "USER_MESSAGE"
}]
})
But pushing in the same array at the same time does render this (this was for the original model, but it's still the same problem, you can't $set and $push in the same array this way):
> db.test_array.updateOne({"step.type":"B"},{$push:{"step.$.configs":{"className":"something"}}, $set:{"step.$.configs.$[secondArray].targetAreaId":"TA-1"}},{arrayFilters:[{"secondArray.targetAreaId":"TA-2"}]})
2019-09-06T13:53:44.783+0200 E QUERY [js] WriteError: Updating the path 'step.$.configs.$[secondArray].targetAreaId' would create a conflict at 'step.$.configs' :

Update an element of an Array in a Document in MongoDB with Mongoose

I have a MongoDB database whith a collection with this structure:
{
"_id" : ObjectId("5b670eefe94672265ca59428"),
"duration" : {
"start" : ISODate("2018-09-01T00:00:00.000Z"),
"end" : ISODate("2018-09-01T00:00:00.000Z")
},
"title" : "Example title.",
"description" : "<p>Hi example!</p>",
"slug" : "title",
"insertDate" : ISODate("2018-08-05T14:51:27.194Z"),
"webData" : [
{
"_id" : ObjectId("5bb1f082931c536950ade361"),
"webCode" : "be_mx",
"categories" : [
{
"_id" : ObjectId("3sdf43f34543et35tret435"),
"name" : "Category 1",
"webCode" : "be_mx",
"slug" : "category-1"
},{
"_id" : ObjectId("3sdf43f34543et35tretert"),
"name" : "Category 2",
"webCode" : "be_mx",
"slug" : "category-2"
}
]
}
],
"__v" : 6,
"lastEditionDate" : ISODate("2018-10-01T10:01:38.889Z")
}
I want to update all documents from this collection that has a categorie with a _id = "3sdf43f34543et35tret435" (in this example the "Category 1"), and I want to update this element category setting, for example, the slug to "category-3".
I tried to do that with this code:
Collection.update({
"webData.categories": {
$elemMatch: {
_id: ObjectId("3sdf43f34543et35tret435")
}
}
}, {
$set: {
webData: {
"categories.$.slug": "category-3"
}
}
}, {
multi: true
}, (err, res) => {
if (err) { console.log(err); }
console.log(res);
});
When I execute that, all the documents that have this category are edited but it's wrong because all the related categories are deleted.
Can you help me with this operation?
Thank you!
EDITED:
When I execute in my DB this query:
db.getCollection("scholarships").update({},
{ '$set': { 'webData.[].categories.$[category].slug': "nana" } },
{ multi: true, arrayFilters: [{ 'category._id': ObjectId("5b719d821f3f1131ec4524f6") }] })
Using in this time an arrayFilter, I receive this error:
The path 'webData.[].categories' must exist in the document in order to apply array updates."

update nested array element value in node js mongoDB [duplicate]

This question already has answers here:
How to Update Multiple Array Elements in mongodb
(16 answers)
Closed 6 years ago.
Hi i am new in nodejs i need to update a value in nested array using _id of document my database document is look like this..
"complaints" : [
{
"complaint" : "head light is not working",
"complaintid" : ObjectId("57205219a56d2b8c0f9274a4"),
"_id" : ObjectId("57454c9249218eb40c1c0d1f"),
"labour" : 350,
"partCost" : 0,
"part" : [
{
"id" : ObjectId("56f12eaab915bd9800272ed7"),
"estimate" : 450,
"partname" : "clutch",
"_id" : ObjectId("57454cef49218eb40c1c0d25"),
"quantity" : 0,
"qrcodes" : []
},
{
"id" : ObjectId("56f12eaab915bd9800272ed7"),
"estimate" : 450,
"partname" : "rear tyre",
"_id" : ObjectId("57454cef49218eb40c1c0d24"),
"quantity" : 0,
"qrcodes" : []
}
],
"acceptance" : true,
"inspection" : false,
"color" : "#8929A9",
"status" : "APPROVED",
"estimate" : 1200,
"solution" : "HEAD LIGHT CHANGE",
"problems" : "HEAD LIGHT IS NOT WORKING"
},
i need to update quantity value of part array exist inside the part array using _id of part array
i am trying this but its not working what should i do for update this value...
var partdata = req.payload.parts;
for(var k = 0; k< partdata.length ; k++ ){
CPS.update({
'complaints.part._id' : partdata[k].partid
}, {
"$inc" : {
'complaints.part.$.quantity' : partdata[k].quantity
}
}).exec
(function(err,temp) {
if(err){
res(err).code(500);
}else{
console.log(temp);
}
});
}
MongoDB doesn't support matching into more than one level of an array.
Consider altering your document model so each document represents an
operation, with information common to a set of operations duplicated
in the operation documents.
Following is not the solution for your case.
But in-case you know the index then you could do something like this:
Assume a sample document like:
{
"_id" : ObjectId("57454c9249218eb40c1c0d1f"),
"part" : [{ "quantity" : 111 }, { "quantity" : 222 }]
}
Then this query should work.
db.test.update({ "_id" : ObjectId("57454c9249218eb40c1c0d1f") }, { "$set" : { "part.1.quantity" : 999 } })
Document will get modified as follows :
{
"_id" : ObjectId("57454c9249218eb40c1c0d1f"),
"array" : [{ "quantity" : 222 }, { "quantity" : 999 }]
}
Update: You can try following way of doing the update. But its not recommended way of doing probably you need to restructure your schema.
db.test.aggregate([
{ "$unwind": "$complaints" },
{ "$unwind": "$complaints.part" },
{ "$project":
{
_id: "$complaints.part._id",
partqty: "$complaints.part.quantity"
}
},
]);
This should return as follows:
{
"_id" : ObjectId("57454cef49218eb40c1c0d25"),
"partqty" : 111
}
{
"_id" : ObjectId("57454cef49218eb40c1c0d24"),
"partqty" : 222
}
Now you can use this information to update, e.g
var cur = db.test.aggregate([
{ "$unwind": "$complaints" },
{ "$unwind": "$complaints.part" },
{ "$project":
{
_id: "$complaints.part._id",
partqty: "$complaints.part.quantity"
}
},
]);
while (cur.hasNext()) {
var doc = cur.next();
//Note the index should be know again :|
db.test.update({ "complaints.part._id": ObjectId("57454cef49218eb40c1c0d25") },
{ "$set": { "complaints.$.part.1.quantity": 55 }},
{ "multi": true})
}

Adding object to array in array in MongoDB

I have this data structure (classes with comments) and I want to add a 1-level deep reply. This means that I'd like to add another object on a "comentarios" element.
How can I achieve this with mongo?
This means: Match cursada (db) id, match clase (first array) id, match comment (second array) id, then add a new element there.
db.cursada.find({"_id": ObjectId("55444f56e5e154f7638b456a")}).pretty()
{
"_id" : ObjectId("55444f56e5e154f7638b456a"),
"clases" : [
{
"_id" : "554e7f2fe5e154797d8b4578",
"titulo" : "qewewqewq"
},
{
"_id" : "554e8be0e5e154dc698b4582",
"titulo" : "la mejor clase"
},
{
"_id" : "554eb90de5e154dd698b458b",
"comentarios" : [
{
"_id" : ObjectId("55a021afe5e154cf098b4567"),
"nombreUsuario" : "nombre",
"texto" : "432432423"
}
],
"titulo" : "Peeling - cosa"
},
{
"_id" : "554e91a0e5e154797d8b4587",
"titulo" : "fdsfdsa"
},
{
"_id" : "554f8f50e5e154dd698b458f",
"titulo" : "clase2"
},
{
"_id" : "554f99dae5e154797d8b45a7",
"titulo" : "con profesor"
},
{
"_id" : "554fa4a0e5e154797d8b45c4",
"titulo" : "profesor nombre nombre"
},
{
"_id" : "5557b37be5e154e07f8b4567",
"titulo" : "Dermatologia I"
},
{
"_id" : "5557c701e5e154066d8b456c",
"titulo" : "Acido hialuronico"
}
],
"curso" : "552fa5f1e5e1542e628b4567",
"fechaFin" : "2015-05-22T03:00:00.000Z",
"fechaIni" : "2015-05-08T03:00:00.000Z",
"titulo" : "cremotas"
}
Getting this result:
{
"_id" : ObjectId("55444f56e5e154f7638b456a"),
"clases" : [
{
"_id" : ObjectId("554eb90de5e154dd698b458b"),
"comentarios" : [
{
"_id" : ObjectId("55a021afe5e154cf098b4567"),
"nombreUsuario" : "nombre",
"texto" : "432432423",
----------------HERE
"replies": [
{ "_id": ....,
"user": ....,
"text":....,
"date":....
}]
----------------HERE
}
],
"titulo" : "Peeling - cosa"
},
]
}
One twisted example!
Luckily it presents no problem to MongoDB and its $elemMatch query operator:
Model.update({
_id: "55444f56e5e154f7638b456a",
classes: {
$elemMatch: {
_id: "554eb90de5e154dd698b458b",
}
}
}, {
$push: {
'classes.$.comentarios': {
nombreUsuario: 'New comment nombreUsuario',
texto: '111242515'
}
}
}, function(err, count) {
console.log('Updated ' + count + ' document');
});
What happens here?
First, we're specyfing specific course ("cursada") to update:
_id: "55444f56e5e154f7638b456a"
Then, using $elemMatch operator, we're restricting result of the query to contain only one class:
classes: {
$elemMatch: {
_id: "554eb90de5e154dd698b458b",
}
}
Now, having found specific class to update, we can finally add new comment to it. Here's our update query:
$push: {
'classes.$.comentarios': {
nombreUsuario: 'New comment nombreUsuario',
texto: '111242515'
}
}
$push operator tells MongoDB to add new comment to specified array of comments.
'classes.$.comentarios' specifies which nested comentarios array to update, using $ positional operator.
Finally, and this part should be self-explanatory: full object of new comment to add to the specified class.
It's also worth mentioning that if you're running into such deeply nested structure, perhaps it's worth thinking about spreading courses, classes, possibly even comments over separate MongoDB collections.
When nested documents are the way to go and when it's better to create separate collections can be actually tricky question to answer - here's nice presentation discussing this issue.

MEAN-Stack MongoDB Sub Array Delete - Works in IDE, not in API

I have a [user] document stored that contains a nested sub-array [profiles],[favorites]. I am simply trying to delete($pull) a favorites from a given profile based on the favorites name.
{
"_id" : ObjectId("558d53eebdd9804820090fa1"),
"name" : "Frank",
"email" : "Frank#FrankTheTank.com",
"profiles" : [
{
"avatar" : "div-male",
"age" : "35",
"gender" : "Male",
"profilename" : "Oly Lifter",
"_id" : ObjectId("558d5404bdd9804820090fa2"),
"favorites" : [
{
"name" : "Power Clean"
},
{
"name" : "Hang Clean"
},
{
"name" : "Clean and Jerk"
}
],
"createdAt" : ISODate("2015-06-26T13:30:44.661Z")
}
],
"createdAt" : ISODate("2015-06-26T13:30:22.884Z"),
"role" : "user",
"__v" : 0
}
Using a MongoDB IDE robomongo, I'm able to successfully remove a favorite item from a known User and Profile ID using this
db.users.update($find: {
'profiles': {
'profiles._id': ObjectId("558d5404bdd9804820090fa2")
},
{
$pull: {
'profiles.$.favorites': {
'name': 'Hang Clean'
}
}
})
However, when I call from my server API using the following syntax, I receive an error, note req.body._id = "558d5404bdd9804820090fa2" and req.body.favorites.name = "Hang Clean"
User.findByIdAndUpdate(_user._id, {
'profiles._id': req.body._id
}, {
$pull: {
'profiles.$.favorites': {
'name': req.body.favorites.name
}
}
}, {
safe: true,
upsert: true
},
function(err, model) {
if (err) {
console.log(err);
return res.status(500).send('Error Deleting Profile');
}
return res.status(200).send('Profile Deleted!');
});
Try updating using the findOneAndUpdate() method since you are supplying the findByIdAndUpdate() method with the wrong parameters: the second argument { 'profiles._id': req.body._id } should be part of the first query object hence you need to use the findOneAndUpdate() method as follows, making sure you convert the string ids into ObjectId's:
var mongoose = require('mongoose');
var id = mongoose.Types.ObjectId(_user._id),
profileId = mongoose.Types.ObjectId(req.body._id),
query = {
"_id": id,
"profiles._id": profileId
},
update = {
"$pull": {
"profiles.$.favorites": { "name": req.body.favorites.name }
}
},
options = { "multi": true, "upsert": true };
User.findOneAndUpdate(query, update, options, function(err, model) {
if(err){
console.log(err);
return res.status(500).send('Error Deleting Profile');
}
return res.status(200).send('Profile Deleted!');
});

Resources