来自Unix的Mongo ObjectID PHP时间?

时间:2015-01-13 09:26:12

标签: php mongodb

我计划使用Mongo ObjectID来比较时间戳,即:

$fourteenDaysAgo = time() - (14 * 86400);

$lookFor = array(
    '_id' => $user
);
$updateFields = array(
    '$pull' => array(
        'Rewards' => array(
            '_id' => array(
                '$lt' => new MongoId(dechex($fourteenDaysAgo).'0000000000000000')
            )
        ),
    ),
);
$returnFields = array(
    '_id' => 1,
);

$userData = $db->users->findAndModify($lookFor, $updateFields, $returnFields);

令我烦恼的是这个具体的

new MongoId(dechex($fourteenDaysAgo).'0000000000000000')

与其他图书馆C#Py相比,这有一种令人不安的" hackish"感觉呢:

ObjectId.from_datetime( fourteen_days_ago )

我一直在查看文档,但似乎无法找到PHP的等价物......它不存在吗?有没有更好的办法?即那些不会让我离开的东西" wtf是我在这里做的?"当我最终在N个月后重新访问这个剧本时?

1 个答案:

答案 0 :(得分:0)

我绝对同意这有点hackish,但它并不像看起来那么糟糕。但要理解,让我们来看看what an ObjectID is made out of。它们是12个字节,用24个字节的十六进制表示

  • 一个4字节的值,表示自Unix纪元以来的秒数,
  • 一个3字节的机器标识符,
  • 一个2字节的进程ID,
  • 一个3字节的计数器,以随机值开始。

通过添加12个零,它会消除构成普通哈希的其余数据。考虑到机器标识符,进程ID和随机计数器是为了防止将相同的ID插入到DB中两次,伪造该数据以进行比较的行为并不是那么糟糕。所有查询都在使用前4个字节。

这种仅dechex时间戳的方法也有可能返回少于8个字节的十六进制,这将导致Mongo丢弃哈希并立即创建一个新哈希值。 (或者,最近,致命错误)我建议:

$timestamp = str_pad(dechex($timestamp), 8, '0', STR_PAD_LEFT);

仔细观察,我们可以看看actual Mongo PHP extension,,我们可以模仿创建过程。如果你需要一个ID,那么它最终会在数据库中结束,我只需要创建一个新ID并换掉前8个十六进制字符:

$id = new MongoId($timestamp.substr(new MongoID(), 8));