Как сделать работу Backbone и MongoDB без проблем?
Приложение My Backbone взаимодействует с REST API, созданным на основе MongoDB, поэтому "естественные" идентификаторы объектов действительно MongoIDs
. После сериализации в JSON они выглядят так:
"_id":{"$id":"505099e998dee4db11000001"}
В документации Backbone упоминается, что вы можете указать другое имя, чем id
для вашего идентификатора идентификатора модели Backbone (используя idAttribute
), однако, поскольку строка MongoIDs представления вложены, просто использование idAttribute: '_id'
не помогает напрямую использовать JSON.
Есть ли способ обойти это, кроме переписывания атрибутов на стороне сервера?
Обновление:
Вот что я делаю на стороне сервера:
$m = new Mongo();
$posts = $m->mydatabase->posts->find();
$out = array();
foreach ($posts as $post) {
$out[] = $post;
}
echo json_encode($out);
Я знаю, что могу сделать что-то вроде $post['id'] = (string) $post['_id']; unset($post['_id']);
, но это именно то, чего я хочу избежать!
Ответы
Ответ 1
Это звучит как хороший пример для parse()
.
Поскольку ваш Mongo JSON заканчивает отправку:
"_id":{"$id":"505099e998dee4db11000001"}
Почему бы не использовать синтаксический анализ Backbone для правильного пространства имен входящих данных?
parse: function(response) {
response.id = response._id['$id'];
delete response._id;
return response;
}
Или что-то вроде этого. Аналогично, поскольку Backbone будет отправлять id как JSON с "id", ваш сервер может взять это и "перевести" его другим способом.
Если вы хотите использовать другой атрибут , _id
, вы просто замените вышеупомянутый синтаксический разбор следующим кодом:
idAttribute: '_id',
parse: function(response) {
response._id = response._id['$id'];
return response;
}
Все, что лучше всего подходит для вас.: -)
Ответ 2
Лучше сделать преобразование в браузере, чтобы вы вывели вычисление с сервера. Итак, вы хотите создать базу MongoModel, а затем вы можете перейти от MongoModel вместо Backbone.Model.
MongoModel = Backbone.Model.extend({
// this handle conversion between the mongo _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;
}
});
Ответ 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, поскольку больше клиентов может захотеть подключиться к нему.
Ответ 4
В 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
Итак, идея состоит в том, чтобы заменить _id в каждом элементе строковой версией BSON:: ObjectId
В позвоночнике вы можете добавить
idAttribute: "_id",
В PHP вы будете использовать разные синтаксис и методы, но я считаю, что вполне возможно повторить это.
Ответ 5
Ваш PHP-код - это REST API, с которым Backbone будет взаимодействовать, поэтому он должен обрабатывать абстрагирование свойства Mongo complex _id
к простой строке id
, которую вы ищете. Это определенно задача API.
Магистраль или любой другой пользователь вашего API не должны ничего знать о Mongo или _id
.
Почему?
Потому что, если вам нужно переключиться с Mongo на другой Db, где нет _id
, тогда ваш API по-прежнему хорош, потому что все, что когда-либо было показано, было id
, что является супер-общим. Таким образом, вы оригинальная идея на самом деле была лучшей идеей (хотя вы хотели бы абстрагировать эту часть кода на то, что можно использовать повторно для всех моделей, а не только для сообщений).