1

我有一个名为 Clickstream 的 MongoDB 集合,并希望在过去 5 天内找到与特定 pubCode 匹配且带有时间戳的所有文档。时间戳位于名为 ts 的字段中,Mongo 数据类型为 Date。

从 Mongo shell 我可以执行以下操作:-

    db.Clickstream.find({
        pubCode : "w_abc123",
        ts: {$gte: ISODate("2014-02-28T00:00:00Z")}
    })

但是,我似乎不能在 Perl 中做同样的事情(使用今天的日期,而不是硬编码的日期和时间)。如果我这样做:-

    my $now = DateTime->now;
    my $n_days_ago = $now->add( days => -5 );
    ... etc ...
    my $ptr = $ptrClickstream->find(
        {
            pubCode => "$pubCode",
            ts => { "\$gte" => ISODate("$n_days_ago") }
        }, 
        { hitType => 1 }
    );

我收到以下错误消息:-

在 recalcPubPop.pm 第 25 行调用了未定义的子例程 &main::ISODate。

如果我像这样删除对 ISOData() 的引用

    my $ptr = $ptrClickstream->find({
        pubCode => "$pubCode", ts => { "\$gte" => "$n_days_ago" }
    });

我没有退回任何文件。

有关如何使此 find() 返回 ts 小于 5 天的记录的任何建议?谢谢!

4

1 回答 1

1

自然地使用DateTime 。只是完整地解释。

ISODate因此,当您从 mongo shell 中看到该表单时,这实际上只是真正存储的底层 BSON Date 的 shell JavaScript 环境的本机表示。

因此,当您检索这些值时,Perl 驱动程序会将这些值“膨胀”DateTime对象,并在您传入这些值时以类似的方式处理到 BSON 日期的转换。

因此,您已经在代码中完成了DateTime数学部分:

my $now = DateTime->now;
my $n_days_ago = $now->add( days => -5 );

->add对于“就地”参考作品,您似乎想要一天的“开始”,以便我们可以截断。

尝试强制执行“UTC”日期,这就是它们在集合中的日期。这只是为了完整性,因为它们通常应该是这样的。您可能会发现这种形式的日期编码更简洁:

my $then = DateTime->now( time_zone => 'UTC' )
             ->truncate( to => 'day' )->add( days => -5 );

你的第二个查询表单通常是正确的,但你真正的问题是你我们通过插值强制转换为字符串"$n_days_ago",所以你没有对象,而是字符串。请参阅我修改过的表格,除非您真的打算这样做,否则不要尝试插值:

my $ptr = $ptrClickstream->find({
    pubCode => $pubCode, ts => { '$gte' => $then } 
});

所以所有这些都对我有用。如果这没有返回结果,请检查您vars的值是否绝对符合您的期望。

所有驱动程序实现都以这种方式为其语言处理本机“日期对象”。

有关详细信息,请参阅日期的驱动程序部分。

于 2014-02-28T02:14:22.547 回答