Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Backbone's and MongoDB's ids work seamlessly?

My Backbone app is communicating with a REST API built on top of MongoDB, so my objects' "natural" ids are really MongoIDs. When serialized into JSON, they look like:

"_id":{"$id":"505099e998dee4db11000001"}

The Backbone documentation mentions that you can specify another name than id for your Backbone model's id attribute (using idAttribute), however, as MongoIDs' string representations are nested, just using idAttribute: '_id' doesn't help in consuming JSON directly.

Is there a way around this, other than rewriting attributes on the server side?

Update:

Here's what I'm doing server-side:

$m = new Mongo();
$posts = $m->mydatabase->posts->find();

$out = array();

foreach ($posts as $post) {
    $out[] = $post;
}

echo json_encode($out);

I know I could do something like $post['id'] = (string) $post['_id']; unset($post['_id']); but it is precisely what I'm looking to avoid!

like image 709
julien_c Avatar asked Sep 12 '12 14:09

julien_c


2 Answers

This sounds like a good example for parse().

Since your Mongo JSON ends up sending:

"_id":{"$id":"505099e998dee4db11000001"}

Why not use the Backbone parse to properly namespace the incoming data?

parse: function(response) {
    response.id = response._id['$id'];
    delete response._id;

    return response;
}

Or something like this. Similarly, since Backbone will be sending the id as JSON with 'id', your server might take that and "translate" it the other way.

If you want to use a different id attribute, _id, you would just replace the above parse with this code:

idAttribute: '_id',

parse: function(response) {
    response._id = response._id['$id'];

    return response;
}

Whatever works best for you. :-)

like image 175
jmk2142 Avatar answered Oct 26 '22 22:10

jmk2142


It's better to do the conversion in the browser so you move the computation off from the server. So you'd want to create a base MongoModel, and then you can extend from MongoModel instead of Backbone.Model.

MongoModel = Backbone.Model.extend({
    // this handle conversion between the mongo's _id and backbone id
    // this is best done on the client side to alleviate server load
    //_id : { "$oid" : ... } <--> id
    parse : function (response) {
        response.id = response._id.$oid;
        delete response._id;
        return response;
    },
    toJSON : function () {
        var
            json = Backbone.Model.prototype.toJSON.apply(this);
        json._id = {'$oid':json.id};
        delete json.id;
        return json;
    }
});
like image 37
MICHAEL PERMANA Avatar answered Oct 26 '22 23:10

MICHAEL PERMANA