1

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 tags 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.

2 Answers 2

1

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?

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. If I use official MongoDB, I had use $pull and $addToSet in an array, but don't know how to use in array of hash. MongoDBx::Class have update method that avoid the $set as per offcial MongoDB api. Having explore for one night, I am thinking another stupid solution, added to orginal post as edit.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.