简体   繁体   中英

Insert MongoDB Server Date from Perl driver

From the MongoDB console, I can:

>  db.log.insert({ dt : new Date })
>  db.log.find().sort({ $natural : -1 }).limit(1)
{ "_id" : ObjectId("50caae2cadd0e471af0b3941"), "dt" : ISODate("2012-12-14T04:42:20.560Z") } 

How can I do the same from the Perl MongoDB driver?

Background

I am using MongoDB with a capped collection for logging. I understand that the ObjectID contains a timestamp, but displaying it and querying it is not simple. I would therefore like to add a server-based timestamp to each entry, but have been unable to figure out how to pass literal commands via the Perl driver.

The Perl MongoDB Driver uses DateTime objects to store Dates, and returns DateTime object back to you if you read dates from the database.

#!/usr/bin/env perl
use strict;
use warnings;
use MongoDB;
use MongoDB::OID;
use DateTime;

# database connection & collection
my $conn  = MongoDB::Connection->new;
my $db    = $conn->dates;
my $log   = $db->log;

# Delete Collection
$log->drop;

# Insert one
my $oid = $log->insert({ dt => DateTime->now });

# Show all
my $all = $log->find;
while ( my $entry = $all->next ) {
    printf "_id: %s dt: %s\n", $entry->{_id}->to_string, $entry->{dt}->format_cldr("dd.MM.yyyy HH:mm:ss");
}

If you execute it, it prints something like

_id: 50cb1b9321d30efd17000000 dt: 14.12.2012 12:29:07

You should also read the DateTime Documentation to understand what you can do with it: http://search.cpan.org/perldoc?DateTime

On the Connection startup you can also set which Date object you want.

http://search.cpan.org/perldoc?MongoDB::Connection#dt_type

If you set it to DateTime::Tiny for example it will be faster. But you should first understand the difference between DateTime and DateTime::Tiny. Read the Documentation of booth and decide in which case the one or the other is better.


The example above creates the client time. If you want the time from the server instead of your client, because client/server are not the same. You can do two things.

At first, create a JavaScript function that returns a Date object und evaluate the function on the server.

# JavaScript function that return a Date object
my $now = MongoDB::Code->new(code => qq{function(){
    return new Date
}});

# later...
my $oid = $log->insert({ 
    dt => $dt,
    st => $db->eval($now),
});

The second possibility. The default "_id" object from MongoDB already contains a timestamp when the object will be created. At least the documentation says it comes from the server, and i hope it really comes from the server and will not created by the driver. But if $entry is your MongoDB result you can get a DateTime object from it this way:

my $dt = DateTime->from_epoch(epoch => $entry->{_id}->get_time);

Example:

#!/usr/bin/env perl
use strict;
use warnings;
use MongoDB;
use MongoDB::OID;
use MongoDB::Code;
use DateTime;

# database connection & collection
my $conn  = MongoDB::Connection->new;
my $db    = $conn->dates;
my $log = $db->log;

# Delete Collection
$log->drop;

# Client Time
my $dt = DateTime->now;

# JavaScript function that return a Date object
my $now = MongoDB::Code->new(code => qq{function(){
    return new Date
}});

# wait 2 seconds to see a difference between
# $dt and the $now function
sleep 2;

# Insert one
$log->insert({ 
    dt => $dt,
    st => $db->eval($now),
});

sleep 2;

$log->insert({ 
    dt => $dt,
    st => $db->eval($now),
});

# Show all
my $dtf = "dd.MM.yyyy HH:mm:ss";
my $all = $log->find;
while ( my $entry = $all->next ) {
    printf "dt: %s\n", $entry->{dt}->format_cldr($dtf);
    printf "st: %s\n", $entry->{st}->format_cldr($dtf);
    printf "_id time: %s\n", DateTime->from_epoch(epoch => $entry->{_id}->get_time)->format_cldr($dtf);
    print "\n";
}

Output:

dt: 14.12.2012 16:29:28
st: 14.12.2012 16:29:30
_id time: 14.12.2012 16:29:30

dt: 14.12.2012 16:29:28
st: 14.12.2012 16:29:32
_id time: 14.12.2012 16:29:32

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM