0

I am working with MongoDB and Perl. Here is my data structure:

{
    "_id" : ObjectId("501976f8005c8b541d000000"),
    "err_id" : "err",
    "solution" : [
        {
            "attachment" : "attach",
            "macr" : "macrs",
            "yammer" : "yam",
            "resolution" : "l",
            "salesforce" : "salesforce",
            "username" : "bob"
        },
        {
            "attachment" : "attach",
            "macr" : "macrs",
            "yammer" : "yam",
            "resolution" : "losssss",
            "salesforce" : "salesforce",
            "username" : "bob"
        }
    ]
}

As you can see, I have an array with objects inside. I have created this using the Perl MongoDB library.

I am familiar with some syntax for manipulating arrays in the Perl MongoDB lib. For example, I use this to find entries with a username the same as $username.

$users->find({"solution.username" => $username});

I thought removing an element would be as simple:

$users->remove({"solution.username" => $username});

But alas, it is not so. I have tried this and using pull, but to no avail! I've had a hard time finding this. Does anybody know the syntax to remove an array element based on the contents of one of its fields?

daxim
  • 39,270
  • 4
  • 65
  • 132
PinkElephantsOnParade
  • 6,452
  • 12
  • 53
  • 91
  • Just like find() returns the whole document, remove() removes the whole document.. – Aafreen Sheikh Aug 01 '12 at 18:55
  • Right on - as it were I actually want to remove the whole document! But it seems that it isn't removing anything at all. Is my example syntax the correct syntax? – PinkElephantsOnParade Aug 01 '12 at 18:56
  • I'm unfamiliar with Perl syntax, but I checked the documentation. It looks ok..If your find() DOES return some documents, then your remove() SHOULD ideally remove all these documents, because your query is exactly the same, as you mention in the example. – Aafreen Sheikh Aug 01 '12 at 19:03
  • Related questions:http://stackoverflow.com/questions/4969768/removing-the-array-element-in-mongodb-based-on-the-position-of-element, http://stackoverflow.com/questions/7227890/how-to-delete-n-th-element-of-array-in-mongodb – Aafreen Sheikh Aug 01 '12 at 19:19
  • 2
    Have you tried checking the error messages? You should call `last_error()` after your run to make sure there wasn't a problem or run `$users->remove({"solution.username" => $username},{safe => 1});` which will croak on error. – zostay Aug 01 '12 at 19:53

1 Answers1

1

The MongoDB::Collection remove() method will remove documents matched by your query .. so definitely not what you are looking for.

To delete specific fields you should use $unset.

Your solution.usernames are actually in an array, so you would have to include an array index for the fields to delete, eg:

$users->update({"_id" => '123'}, {
   '$unset' => {
       'solution.0.username' => 1,
       'solution.1.username' => 1
   }
});

I'm not aware of a shorter syntax to unset all fields matching username within the solution array, but you can add multiple solution.#.username fields to the $unset command.

My example above deletes the first two username entries from the array. If the matching document(s) had more than two username entries, each time you ran this update you would delete up to two more entries (if they exist).

Stennie
  • 63,885
  • 14
  • 149
  • 175