我必须从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)
答案 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
生成器的情况下实现其他语言的功能。