What I am trying to do is add a new {field:value} for a blog post. So for example, if I wanted to start tracking impressions on websites.blog_posts.url: 'http://www.example.com/01.html' how can I add that impressions attribute for that blog post?
My current document structure:
{
email_address: '[email protected]',
password: 'random_password',
first_name: 'John',
last_name: 'Doe',
user_type: 'WEBMASTER',
newsletter: 'NO',
websites: [{
main_title: 'My Blog Website',
main_url: 'http://www.example.com',
blog_posts: [{
url: 'http://www.example.com/01.html',
title:'My first blog post',
description: 'My first description.'
}, {
url: 'http://www.example.com/02.html',
title: 'My second blog post',
description: 'My second description.'
}, {
url: 'http://www.example.com/03.html',
title: 'My third blog post',
description: 'My third description.'
}, {
url: 'http://www.example.com/04.html',
title: 'My fourth blog post',
description: 'My fourth description.'
}]
}]
}
Here is what I thought would work using update and making upsert TRUE.
db.my_collection.update( {'websites.blog_posts.url': 'http://www.example.com/01.html' }, {'$set': {'websites.blog_posts.impressions': 549}}, true )
The error that I received is: *can't append to array using string field name [blog_posts]*
Maybe "$set" is not correct for this or maybe I can not reference that deep with dot notation? I just started using MongoDB yesterday, any help would be great.
Thank you!
To add field or fields to embedded documents (including documents in arrays) use the dot notation. See example. To add an element to an existing array field with $addFields , use with $concatArrays .
Update Documents in an ArrayThe positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator.
So, Adding a new field to an array is possible by using the update operation. $push operator is used to insert the field inside the array and if we want to add multiple fields, use $each inside $push.
Starting from MongoDB 4.2 you can perform Updates with an Aggregation Pipeline. An aggregation pipeline enables more expressive updates including calculated fields and references to other field values in the same document.
What you're trying to do is not possible given your schema. Dot-notation can be multi level but if there's more than one level that is an array it can no longer be addressed using the positional operator '$'.
E.g. you'd need to do :
db.my_collection.update(
{'websites.blog_posts.url': 'http://www.example.com/01.html' },
{'$set': {'websites.$.blog_posts.$.impressions': 549}},
true );
But having two position operators in the update is not possible since MongoDB can only determine the position of an element in the first array.
Your only option is to redesign your schema to have a dedicated collection of user websites (which is better for other reasons too in this case).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With