如何使Backbone和MongoDB的id无缝工作?

时间:2012-09-12 14:32:35

标签: php mongodb backbone.js

我的Backbone应用程序正在与构建在MongoDB之上的REST API进行通信,因此我的对象的“自然”ID实际上是MongoIDs。当序列化为JSON时,它们看起来像:

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

Backbone documentation提到您可以为您的Backbone模型的id属性指定另一个名称而不是id(使用idAttribute),但是,由于MongoIDs的字符串表示是嵌套的,只需使用{ {1}}无法直接使用JSON。

除了在服务器端重写属性之外,还有其他方法吗?

更新:

这就是我在服务器端做的事情:

idAttribute: '_id'

我知道我可以做$m = new Mongo(); $posts = $m->mydatabase->posts->find(); $out = array(); foreach ($posts as $post) { $out[] = $post; } echo json_encode($out); 之类的事情,但这正是我想要避免的事情!

5 个答案:

答案 0 :(得分:16)

这听起来像是parse()的一个很好的例子。

由于您的Mongo JSON最终发送:

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

为什么不使用Backbone解析来正确命名传入数据呢?

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

    return response;
}

或类似的东西。同样,由于Backbone将使用'id'将ID作为JSON发送,您的服务器可能会采用该方式并以另一种方式“翻译”它。

如果您想使用其他id attribute_id,则只需使用以下代码替换上述解析:

idAttribute: '_id',

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

    return response;
}

什么最适合你。 : - )

答案 1 :(得分:5)

最好在浏览器中进行转换,以便从服务器上移除计算。所以你想要创建一个基本MongoModel,然后你可以从MongoModel而不是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;
    }
});

答案 2 :(得分:3)

查看各种建议的选项,我发现最简单的方法是做你想要避免的事情。 (使用解析确实可以工作)

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

$out = array();

foreach ($posts as $post) {
    // populate an id field
    $post['id']=$post['_id']->{'$id'},
    $out[] = $post;
}

echo json_encode($out);

如果您希望模型在同步时将其发回,请保持$post['_id']。 我更喜欢更正API,因为更多客户端可能想要连接到它。

答案 3 :(得分:0)

在Ruby中,我能够做到以下几点:

items.find.to_a.map do |item|
  frombsonid(item)
end.to_json

def frombsonid(obj) obj.merge({'_id' => obj['_id'].to_s}) end

当您获得数据时,您可以将字符串转换为BSON :: ObjectId

def tobsonid(id) BSON::ObjectId.fromstring(id) end

因此,我们的想法是用字符串版本BSON :: ObjectId

替换每个项目中的_id

在骨干中你可以添加

idAttribute: "_id", 

在PHP中,您将使用不同的语法和方法,但我相信很有可能复制它。

答案 4 :(得分:0)

您的PHP代码是Backbone将与之交互的REST API,因此 it 应该处理Mongo的复杂_id属性到简单id字符串的抽象寻找。这绝对是API的工作。

Backbone或您API的任何其他消费者,不应该对Mongo或_id了解任何信息。

为什么呢? 因为如果你要从Mongo切换到没有_id的其他Db,那么你的API仍然很好,因为所有暴露的都是id,这是超级通用的。所以你最初的想法实际上是最好的想法(尽管你想要将这段代码抽象成可以重用于所有模型的东西,而不仅仅是帖子)。