1

I have a Perl script that pulls a table from a SQL database ($row variable) and attempts to do a MongoDB update like so:

my $res = $users->update({"meeting_id" => $row[0]},
            {'$set' => {
                "meeting_id" => $row[0],
                "case_id" => $row[1],
                "case_desc" => $row[2],
                "date" => $row[3],
                "start_time" => $row[4],
                "end_time" => $row[5],
                #"mediator_LawyerID" => $row[6],
                "mediator_LawyerIDs" => \@medLawIds,
                "case_number" => $row[6],
                "case_name" => $row[7],
                "location" => $row[8],
                "number_of_parties" => $row[9],
                "case_manager" => $row[10],
                "last_updated" => $row[11],
                "meeting_result" => $row[12],
                "parties" => \@partyList
                }},
                {'upsert' => 1}) or die "I ain't update!!!";

My client now wants ICS style calendar invites sent to their mediators. Thus, I need to know whether an update or insert happened. The documentation for MongoDB::UpdateResult implies that this is how you access such a property:

my $id = $res->upserted_id;

So I tried:

bless ($res,"MongoDB::UpdateResult");
my $id = $res->upserted_id;

After this code $id is like:

HASH(0x356f8fc)

Are these the actual IDs? If so, how do I convert to a hexadecimal string that can be cast to Mongo's ObjectId type? It should be noted I know absolutely nothing about perl; if more of the code is relevant, at request I will post any section ASAP. Its 300 lines so I didn't want to include the whole file off the bat.

EDIT: I should mention before anyone suggests this that using update_one instead of update returns the exact same result.

awimley
  • 692
  • 1
  • 9
  • 29

1 Answers1

1

HASH(0x356f8fc) is a Perl Hash reference. It's basically some kind of (internal) memory address of some data.

The easiest way to get the contents is Data::Dumper:

use Data::Dumper
[...]
my $result = $res->upserted_id;
print Dumper($result);

HASH(0x356f8fc) is just the human readable representation of the real pointer. You must dump it in the same process and can't pass it from one to another.

You'll probably end up with something like

`my $id = $result->{_id};`

See the PerlRef manpage for details.

See also the MongoDB documentation about write concern.

PS: Also remember that you could use your own IDs for MongoDB. You don't need to work with the generated ones.

Sebastian
  • 2,472
  • 1
  • 18
  • 31
  • Is there some better way to check whether an upsert statement did an update or an insert? – awimley Apr 28 '16 at 20:34
  • This solution certainly checks the hash correctly it seems, returns $VAR1 = undef; – awimley Apr 28 '16 at 20:37
  • I suggest to also dump the MongoDB result (your `$res`) - it might contain this information. Otherwise, if you feed sequentially and not in parallel, do the most likely operation first (for example, insert) and fall back to the other one (for example, update) if the first fails. – Sebastian Apr 28 '16 at 20:38
  • Did you just try `print Dumper("HASH(0x356f8fc)");` or added the Dumper to your original script? A point cannot be copied outside the script, your `HASH(0x356f8fc)` doesn't contain any information! – Sebastian Apr 28 '16 at 20:39
  • I added use Data::Dumper; Then printed the hash reference in the original script using Dumper. – awimley Apr 28 '16 at 20:42
  • Do I perhaps have to wait in some way before attempting to access the memory address? It was my understanding that perl is synchronous by default, and I could print the update result immediately after calling update. – awimley Apr 28 '16 at 20:54
  • Yes, you could: `$x = { foo => bar }; print Dumper($x);` - working immediately. Did you try Dumper on the MongoDB result `$res`? – Sebastian Apr 29 '16 at 06:07
  • That works: $VAR1 = bless( { 'write_errors' => [], 'write_concern_errors' => [], 'matched_count' => 1, 'modified_count' => 1, 'upserted_id' => undef }, 'MongoDB::UpdateResult' ); – awimley Apr 29 '16 at 13:29
  • This seems to claim it matched one document, but is unable to provide me with the ID of the document updated? I accepted your answer as upserted_id is now exposed, though it continues to be undef even when matched_count is 1. – awimley Apr 29 '16 at 13:30
  • upsert is typicall the *insert* part of the update-insert-combination. `upserted_id` is probably only set if a new document has been created. You should give it a try. – Sebastian Apr 29 '16 at 13:55