MongoDB--add/drop elements in a field of array of hash how to
I am using perl MongoDBx::Class, following the tutorial I inserted the document below. The tags field is an array of hash. Tried to remove tag and add tag using mongodb's $pull and $addToSet function without success.
How to add/drop elements to/from ta开发者_JAVA技巧gs field? If you are not a perl programmer, answer in mongodb shell command also wlcome.
Thanks.
my $novel = $novels_coll->insert({
_class => 'Novel',
title => 'The Valley of Fear',
year => 1914,
author => {
first_name => 'Arthur',
middle_name => 'Conan',
last_name => 'Doyle',
},
added => DateTime->now(time_zone => 'Asia/Jerusalem'),
tags => [
{ category => 'mystery', subcategory => 'thriller' },
{ category => 'mystery', subcategory => 'detective' },
{ category => 'crime', subcategory => 'fiction' },
],
});
This is the document inserted:
{
"_id": {
"$oid": "4e27eae3008a6ee40f000000"
},
"_class": "Novel",
"added": "2011-07-21T12:01:23+03:00",
"author": {
"middle_name": "Conan",
"last_name": "Doyle",
"first_name": "Arthur"
},
"tags": [
{
"subcategory": "thriller",
"category": "mystery"
},
{
"subcategory": "detective",
"category": "mystery"
},
{
"subcategory": "fiction",
"category": "crime"
}
],
"title": "The Valley of Fear",
"year": 1914
}
Edit:
After deeper exploration of MongoDBX, the update method overrided offical MongoDB driver, so the $pull, $addToSet may not work. I will use this stupid method:
my $novel = $novel_coll->find_one({ some criteria });
my @tags = $novel->tags;
my @updated_tags = grep(unless($tag{category=>CATEGORY}, @tags); #to pull out unwanted tag. Or use push to add new tag.
$novel->update({tags=>\@updated_tags});
I hope MongoDBx has method to updated arrayRef field.
I'll do this in mongo shell syntax, convert to perl as needed :
ADD :
db.novels_coll.update({_id: ID, ...other criteria...}, {$addToSet:{tags:{subcategory:SUBCATEGORY, category:CATEGORY}}})
REMOVE BY CATEGORY :
db.novels_coll.update({_id: ID, ...other criteria...}, {$pull:{tags:{category:CATEGORY}}})
REMOVE BY CATEGORY AND SUBCATEGORY :
db.novels_coll.update({_id: ID, ...other criteria...}, {$pull:{tags:{category:CATEGORY, subCategory: SUBCATEGORY}}})
Does that answer your question?
I am the author of MongoDBx::Class.
When using MongoDBx::Class, you have two options to update a document:
The regular, MongoDB way, by using the update() method on the collection object:
$collection->update({ _id => $document->_id }, { '$addToSet' => { tags => { category => 'drama', subcategory => 'chick-flick' } } });
This allows you to perform all of MongoDB's modifiers such as $addToSet, $push, $pull, etc.
The MongoDBx::Class way, by using the update() method on the document object:
$document->update({ tags => \@new_tags });
This is faster and somewhat cleaner, but it only really performs the $set modifier, so whatever you provide to the "tags" attribute in the example above will be the new value of that attribute.
Hope this helps, Ido.
精彩评论