How to remove an object which is inside [nested] of an object which is in an object array [MongoDB]? - mongodb

I have a document:
{
"Name": "Downhill 3",
"Apartments": [
{
"Yardage": 55.5,
"Owner": {
"name" : "Timothy",
"surname" : "Notclement",
"phone" : 555666777
}
},
{
"Yardage": 70,
"Owner": {
"name" : "Anya",
"surname" : "Joylor-Tay",
"phone" : 555111000
}
}
]
}
It represents "all" apartments at some street.
I want to delete one entry from Apartments array, let's say the one which is owned by Anya, by specifying it by something like this Apartments.Owner.name:"Anya".
How can I perform such an operation? I tried to $pull and to $unset, but nothing worked. Now I came across findAndModify (docs here) and possibility to use an aggregation pipeline in the update field, but can't really figure out how to form a query.
Mongo commands I tried:
db.ApartCollection.update( { "_id":ObjectId("example123") }, { $unset: { "Apartments.Owner.name" : "Anya" } } )
db.ApartCollection.update( { "_id":ObjectId("example123") }, { $unset: { Apartments: { "Owner.name" : "Anya" } } } )
db.ApartCollection.update( { "_id":ObjectId("example123") }, { $pull: { Apartments: { "Owner.name" : "Anya" } } } )
db.Dokumenty.update( { "_id":ObjectId("61881be8dd6d25184a3b6c3f") }, { $pull: { "Apartments.Owner.name": "Anya" } } )
^This one doesn't even ?compile? It returns error:
Cannot use the part (Owner) of (Apartments.Owner.name) to traverse the element ({Apartments:...blah blah

Related

How to update Meteor array element inside a document

I have a Meteor Mongo document as shown below
{
"_id" : "zFndWBZTvZPgSKXHP",
"activityId" : "aRDABihAYFoAW7jbC",
"activityTitle" : "Test Mongo Document",
"users" : [
{
"id" : "b1#gmail.com",
"type" : "free"
},
{
"id" : "JqKvymryNaCjjKrAR",
"type" : "free"
},
],
}
I want to update a specific array element's email with custom generated id using Meteor query something like the below.
for instance, I want to update the document
if 'users.id' == "b1#gmail.com" then update it to users.id = 'SomeIDXXX'
So updated document should looks like below.
{
"_id" : "zFndWBZTvZPgSKXHP",
"activityId" : "aRDABihAYFoAW7jbC",
"activityTitle" : "Test Mongo Document",
"users" : [
{
"id" : "SomeIDXXX",
"type" : "free"
},
{
"id" : "JqKvymryNaCjjKrAR",
"type" : "free"
},
],
}
I have tried the below but didnt work.
Divisions.update(
{ activityId: activityId, "users.id": emailId },
{ $set: { "users": { id: _id } } }
);
Can someone help me with the relevant Meteor query ? Thanks !
Your query is actually almost right except for a small part where we want to identify the element to be updated by its index.
Divisions.update({
"activityId": "aRDABihAYFoAW7jbC",
"users.id": "b1#gmail.com"
}, {
$set: {"users.$.id": "b2#gmail.com"}
})
You might need the arrayFilters option.
Divisions.update(
{ activityId: activityId },
{ $set: { "users.$[elem].id": "SomeIDXXX" } },
{ arrayFilters: [ { "elem.id": "b1#gmail.com" } ], multi: true }
);
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/
You need to use the $push operator instead of $set.
{ $push: { <field1>: <value1>, ... } }

MongoDB remove all matching items from sub-sub-array

Just wondering what the best way to accomplish this is. I can think of some janky ways, but they don't seem right.
What I'm trying to do is remove all sub-sub-array objects from a documents. Like follows:
SCHEMA
schema {
person: Array<{
id: string;
posts: Array<{
id: string,
comments: Array<{
id: string
tagged_person_id: string;
}>
}>
}>
}
What I am looking for some way to delete all comments in every post for each person where the comment has tagged_person_id == some_id. This isn't my actually use-case, but it represents the same concept.
I know how to use $pull to remove from a subarray for one subdocument, but just not sure how to accomplish all of this in one query, or if it's even possible.
As per JIRA ticket SERVER-1243 and the documentation, starting with MongoDB v3.5.12, given the following document:
{
"posts" : [
{
"comments" : [
{
"tagged_person_id" : "x"
},
{
"tagged_person_id" : "y"
}
]
},
{
"comments" : [
{
"tagged_person_id" : "x"
}
]
},
{
"comments" : [
{
"tagged_person_id" : "y"
}
]
}
]
}
You can run this update:
db.collection.update({}, {
$pull : {
"posts.$[].comments" : {"tagged_person_id": "x"}
}
})
in order to remove all comments where tagged_person_id is equal to "x".
Result:
{
"posts" : [
{
"comments" : [
{
"tagged_person_id" : "y"
}
]
},
{
"comments" : []
},
{
"comments" : [
{
"tagged_person_id" : "y"
}
]
}
]
}

Using MongoDB $set to update multiple subdocuments

I have such Article-documents:
{
"_id" : "rNiwdR8tFwbTdr2oX",
"createdAt" : ISODate("2018-08-25T12:23:25.797Z"),
"title" : "Happy",
"lines" : [
{
"id" : "5efa6ad451048a0a1807916c",
"text" : "Test 1",
"align" : "left",
"indent" : 0
},
{
"id" : "ae644f39553d46f85c6e1be9",
"text" : "Test 2"
},
{
"id" : "829f874878dfd0b47e9441c2",
"text" : "Test 3"
},
{
"id" : "d0a46ef175351ae1dec70b9a",
"text" : "Test 4"
},
{
"id" : "9bbc8c8d01bc7029220bed3f",
"text" : "Test 5"
},
{
"id" : "6b5c02996a830f807e4d8e35",
"text" : "Test 6",
"indent" : 0
}
]
}
I need to update some Lines.
For example I have array with ids of the line which must be updated.
let lineIds = [
"5efa6ad451048a0a1807916c",
"829f874878dfd0b47e9441c2",
"6b5c02996a830f807e4d8e35"
];
So I try to update attributes "attr" for the "lines" and I do following:
'articles.updateLines': function (articleId, lineIds, attr, value) {
return Articles.update({
'_id': articleId,
'lines.id': { $in: lineIds }
},
{
$set: {
['lines.$.' + attr]: value
}
},
{ multi: true }
);
}
The problem is that just the first line (with id="5efa6ad451048a0a1807916c") is updated.
Any ideas? Thanks! :)
You can use $[]. This will works only MongoDB version 3.6 and above.
Refer link :
https://docs.mongodb.com/manual/reference/operator/update/positional-all/
You can also see this stackoverflow question reference:
How to add new key value or change the key's value inside a nested array in MongoDB?
You can convert below query in your function
db.col.update(
{ '_id':"rNiwdR8tFwbTdr2oX", },
{ $set: { "lines.$[elem].text" : "hello" } },
{ arrayFilters: [ { "elem.id": { $in: lineIds } } ],
multi: true
})
'lines.id': { $in: lineIds }
This won't work, because lines is an array.
What I understand from your question, you can prepare a new array with proper processing and replace the lines array with the new one. Here is an idea how to do this:
'articles.updateLines': function (articleId, lineIds, attr, value) {
let lines = Articles.findOne(articleId).lines;
// prepare a new array with right elements
let newArray = [];
for(let i=0; i<lines.length; i++){
if(lineIds.includes(lines[i].id)){
newArray.push(value)
}
else newArray.push(lines[i])
}
return Articles.update({
'_id': articleId,
},
{
$set: {
lines: newArray
}
}
);
}

push to list based mongodb

I would like to update the following structure:
record = {'_id':some_id,
'status': { 1 : {
'events' : [a,b,c ],
'other_stuff' : { }
}
{ 2 : {
'events' : [a,b,c ] },
'other_stuff' : { }
} ,
}
,
'other_key':{...}
}
Now what I want to do is, with status code = 3 and and event list = ['x','y','z'] I would like to have:
record = {'_id':some_id,
'status': { 1 : {
'events' : [a,b,c],
'other_stuff' : { }
},
{ 2 : {
'events' : [a,b,c ] },
'other_stuff' : { }
} ,
{ 3 : {
'events' : [x,y,z ] },
} ,
}
,'other_key':{...}
}
Is there a fast way to get this done without too much maneuvering?
You can use the dot notation to specify the embedded document in your $set as follows:
db.collection.updateOne(
{ "_id": ObjectId("5852bc9eade47a3353ff01d0") },
{
"$set": {
"status.3": {
"events" : ["x","y","z"]
}
}
}
)

Mongodb: Finding and updating object property from array

I have a collection with multiple documents which follow this structure:
{
"_id" : {
"oid" : XXX
},
"name" : "Name",
"videos" [
{
"id" : 1,
"thumbnail" : "thumbnail.jpg",
"name" : "Name here"
},
{
"id" : 2,
"thumbnail" : "thumbnail.jpg",
"name" : "Name here"
},
{
"id" : 3,
"thumbnail" : "thumbnail.jpg",
"name" : "Name here"
}
]
}
I want to find and update the a thumbnail of a video, of which I only know the id, but not which document it is in.
This is what I've tried so far, but it's not working properly. All the examples I found relied on knowing the document id, and the array position of the object to update. I also found that doing a query like this found the document okay, but set the whole document as the new thumbnail!
db.collection(COLLECTION-NAME, function(err, collection){
collection.update(
{ 'videos.id' : 2 },
{ $set: { thumbnail: "newThumbnail.jpg" } },
function(err, result){
if (!err){
console.log('saved', result)
} else {
console.log('error', err);
}
}
);
});
Use the $ positional operator to update the value of the thumbnail field within the embedded document having the id of 2:
db.collection.update(
{ "videos.id": 2 },
{ "$set": { "videos.$.thumbnail" : "newThumbnail.jpg" } }
)