MongoDB Clone on top of Postgres


Mongolike is an experimental MongoDB clone being built on top of PLV8 and Postgres.

  • create_collection()
  • drop_collection()
  • save()
  • find()
  • runCommand() (Map/Reduce)
  • ensureIndex()
  • removeIndex()
  • getIndexes()

Visit and follow the build instructions.

The easy way to install is to use node.js.

$ npm install -g mongolike
$ mongolike-install -d yourdb
$ psql yourdb <sql/*.sql

Mongolike includes a test suite and a test runner.

$ test/test_runner.js -d yourdb

Additional tests can be added to test/tests.sql.

All commands must be prefixed by SELECT, and are modified slightly to work in the Postgres environment.

Create a collection.


SELECT create_collection('test');

Drop a collection.


SELECT drop_collection('test');

Save an object into a collection.


SELECT save('test', '{ "foo": "bar" }');

Find an object, with optional terms, limit, and skip.


SELECT find('test', '{ "type": { "$in": [ "food", "snacks" ] } }');

Run a command on the Database. Currently only mapReduce is supported.

NOTE The JSON object cannot have carriage returns, the example below does for readability.


SELECT runCommand('{
  "map": "function MapCode() {
    emit(this.Country, {
      \"data\": [
          \"city\": this.City, 
          \"lat\":  this.Latitude, 
          \"lon\":  this.Longitude
  "reduce": "function ReduceCode(key, values) {
    var reduced = {
      \"data\": [ ]
    for (var i in values) {
      var inter = values[i];
      for (var j in {[j]);
    return reduced;
  "mapreduce": "cities",
  "finalize": "function Finalize(key, reduced) {
    if ( == 1) {
      return {
        \"message\" : \"This Country contains only 1 City\"

    var min_dist = 999999999999;
    var city1 = { \"name\": \"\" };
    var city2 = { \"name\": \"\" };
    var c1;
    var c2;
    var d;

    for (var i in {
      for (var j in {
        if (i >= j) continue;
        c1 =[i];
        c2 =[j];
        d = Math.sqrt((*(*(c1.lon-c2.lon));

        if (d < min_dist && d > 0) {
          min_dist = d;
          city1 = c1;
          city2 = c2;
    return {
      \"dist\": min_dist
  }" }');

Creates a new index on a collection.


SELECT ensureIndex('test', '{ "foo", "bar" }', '{ "unique": true }');

Removes an index from a collection by name.


SELECT removeIndex('test', 'idx_col_woo_foo');

Removes an index from a collection by terms.

NOTE in order to remove an index with terms you MUST cast the query due to how Postgres handles JSON.


SELECT removeIndex('test', '{ "foo", "bar" }'::json);

Retrieves all indexes for a given collection.


SELECT getIndexes('test');

I have included a modest amount of data for testing and benchmarking, both for Postgres and for MongoDB (1,706,873 rows).

Importing into Postgres:

$ psql yourdb < data/cities.sql

This will create the collection and save() all of the data.

Importing into MongoDB

$ mongoimport --collection cities --type csv --headerline --file data/cities.csv --db yourdb

Follow along at