I have to import a lot of data into MongoDB from MySQL and I'd like to use the timestamp from the ObjectID instead of storing it in a separate key/value (as it is in the existing data). In order to do this I'd need to create an ObjectID for the existing data with a date from the past. I also need to do this using the PHP driver. I've read that there might be a way to do this in Python, Java and Node.JS so I thought maybe there was an equivalent method in PHP.
If this is possible - is it safe to do? Meaning and I going to have issues with duplicate or invalid ObjectIDs? Thanks.
In Node.JS:
var timestamp = Math.floor(new Date().getTime()/1000);
var objectId = new ObjectID(timestamp);
Below is from: MongoDB using timestamps to sort
In Python:
gen_time = datetime.datetime(2010, 1, 1)
dummy_id = ObjectId.from_datetime(gen_time)
In Java:
Date d = new Date(some timestamp in ms);
ObjectId id = new ObjectId(d)
ObjectID is automatically generated by the database drivers, and will be assigned to the _id field of each document. ObjectID can be considered globally unique for all practical purposes. ObjectID encodes the timestamp of its creation time, which may be used for queries or to sort by creation time.
ObjectId is one data type that is part of the BSON Specification that MongoDB uses for data storage. It is a binary representation of JSON and includes other data types beyond those defined in JSON. It is a powerful data type that is incredibly useful as a unique identifier in MongoDB Documents.
MongoDB does not have out-of-the-box auto-increment functionality, like SQL databases. By default, it uses the 12-byte ObjectId for the _id field as the primary key to uniquely identify the documents.
An ObjectID is a 12-byte Field Of BSON type. The first 4 bytes representing the Unix Timestamp of the document. The next 3 bytes are the machine Id on which the MongoDB server is running. The next 2 bytes are of process id. The last Field is 3 bytes used for increment the objectid.
Right now, the PHP driver has no built in functionality for this, the __set_state() that the other answer mentioned is only for being able to session-deserialize the ID and doesn't allow you to create it through the specific components.
You will have to do the following to automatically create an 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() ) );
?>
If you are using the MongoId just for comparison, for example, selecting all records within a date range, you don't need a fully valid id. So you could simply do:
$id = new \MongoId(dechex($timestamp) . str_repeat("0", 16));
Just be sure to never insert this id and just use it for $gte/$gt/$lt/$lte queries.
edit
My bad, the above snippet would work with dates before about 1979 as dechex($timestamp)
doesn't always return 8 characters, so a better snippet would be:
$id = new \MongoId(sprintf("%08x%016x", $timestamp, 0));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With