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

使用PHP驱动程序从过去的日期创建MongoDB对象ID,php,mongodb,Php,Mongodb,我必须从MySQL将大量数据导入MongoDB,我希望使用ObjectID中的时间戳,而不是将其存储在单独的键/值中(就像在现有数据中一样)。为了做到这一点,我需要为现有数据创建一个ObjectID,日期来自过去。我还需要使用PHP驱动程序来实现这一点。我已经读到,在Python、Java和Node.JS中可能有一种方法可以做到这一点,所以我认为在PHP中可能有一种等效的方法 如果这是可能的-这样做安全吗?我和Means在重复或无效objectid方面会有问题吗?谢谢 在Node.JS中: va

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

如果这是可能的-这样做安全吗?我和Means在重复或无效objectid方面会有问题吗?谢谢

在Node.JS中:

var timestamp = Math.floor(new Date().getTime()/1000);
var objectId = new ObjectID(timestamp);
以下资料来自:

在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)

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

看起来有一种趋势是允许使用一些参数创建ObjectId,事实上,这里几乎谈到了它:

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


然而,atm,我相信如果不编写自己的
ObjectId
generator,就无法实现其他语言中的功能。

现在,PHP驱动程序没有内置的功能,即u set\u state()提到的另一个答案仅用于会话反序列化ID,不允许通过特定组件创建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() ) );
?>

如果您使用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));

如果我在按时间戳升序的循环中执行这些插入,我可以编辑此函数以传入$lastTimestamp值并更改以下内容:静态$inc=0;如果($lastTimestamp>0&&$lastTimestamp!=$yourtimstamp)$inc=0;它似乎对我有用,但我只是想检查一下这个没有问题。user1114701,是的,应该可以,但你不应该这样做$inc应该总是递增的,而不是每个时间戳都有。