使用PHP驱动程序从过去的日期创建MongoDB ObjectID

时间:2013-01-17 00:05:45

标签: php mongodb

我必须从MySQL导入大量数据到MongoDB中,我想使用ObjectID中的时间戳,而不是将其存储在单独的键/值中(就像在现有数据中一样)。为了做到这一点,我需要为现有数据创建一个ObjectID,其中包含过去的日期。我还需要使用PHP驱动程序执行此操作。我已经读过在Python,Java和Node.JS中可能有一种方法可以做到这一点,所以我想也许在PHP中有一个等效的方法。

如果可以的话 - 这样做是否安全?意思是我会遇到重复或无效的ObjectID问题?感谢。

在Node.JS中:

var timestamp = Math.floor(new Date().getTime()/1000);
var objectId = new ObjectID(timestamp);

以下是:MongoDB using timestamps to sort

在Python中:

gen_time = datetime.datetime(2010, 1, 1)
dummy_id = ObjectId.from_datetime(gen_time)

在Java中:

Date d = new Date(some timestamp in ms);
ObjectId id = new ObjectId(d)

3 个答案:

答案 0 :(得分:9)

目前,PHP驱动程序没有内置的功能,__ set_state(),另一个答案提到的只是能够对ID进行会话反序列化,并且不允许您通过特定组件创建它

您必须执行以下操作才能自动创建ID:

<?php
function createId( $yourTimestamp )
{
    static $inc = 0;

    $ts = pack( 'N', $yourTimestamp );
    $m = substr( md5( gethostname()), 0, 3 );
    $pid = pack( 'n', posix_getpid() );
    $trail = substr( pack( 'N', $inc++ ), 1, 3);

    $bin = sprintf("%s%s%s%s", $ts, $m, $pid, $trail);

    $id = '';
    for ($i = 0; $i < 12; $i++ )
    {
        $id .= sprintf("%02X", ord($bin[$i]));
    }
    return new MongoID($id);
}

var_dump( createId( time() ) );
?>

答案 1 :(得分:7)

如果您仅使用MongoId进行比较,例如,选择日期范围内的所有记录,则不需要完全有效的ID。所以你可以这样做:

$id = new \MongoId(dechex($timestamp) . str_repeat("0", 16));

请务必不要插入此ID,只需将其用于$ gte / $ gt / $ lt / $ lte查询。

修改

我的不好,上面的代码片段可以使用大约1979年之前的日期,因为dechex($timestamp)并不总是返回8个字符,所以一个更好的代码段将是:

$id = new \MongoId(sprintf("%08x%016x", $timestamp, 0));

答案 2 :(得分:0)

这可能会产生问题,因为使objectid唯一的因素之一是时间部分,但它应该在同一时间内增加多个插入的最后一个字节(或左右)。

看起来有一些允许用一些参数创建ObjectId的动作,事实上它几乎在这里谈论它:http://php.net/manual/en/mongoid.set-state.php

  

理论上,用于创建新id的属性数组。但是,由于MongoId实例没有属性,因此不使用它。

但是,无论如何,我都无法在不编写自己的ObjectId生成器的情况下实现其他语言的功能。