Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create MongoDB ObjectID from date in the past using PHP driver

Tags:

php

mongodb

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)
like image 735
user1114701 Avatar asked Jan 17 '13 00:01

user1114701


People also ask

How MongoDB ObjectId is generated?

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.

What datatype is ObjectId from MongoDB?

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.

Is MongoDB ObjectId incremental?

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.

What is new ObjectId in MongoDB?

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.


2 Answers

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() ) );
?>
like image 65
Derick Avatar answered Sep 23 '22 15:09

Derick


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));
like image 21
gwk Avatar answered Sep 23 '22 15:09

gwk