Я создаю REST-сервис в стиле CRUD с Node.js, Express и MongoDB, используя mongoose. Этот сервис позволит пользователям уже существующего приложения для Android загружать/синхронизировать содержимое своих отдельных баз данных в Интернете.
Модель данных для уже существующего приложения использует UUID (сгенерированные в Java), которые конфликтуют с более короткими, монотонными полями стиля MongoDB _id
. Поскольку модель данных уже существует и заполняется данными от многих пользователей, я не могу преобразовать исходные данные в монотонный стиль MongoDB _id
. Это оставляет мне 2 варианта, которые я могу придумать: 1) заставить Mongo/Mongoose (или какой-нибудь другой ODM) играть с полными UUID вместо монотонных _id
или 2) добавить поле uuid к модели mongoose в дополнение к _id
поле и бороться с подводными камнями этого подхода. Я пытаюсь выбрать вариант № 1 и сталкиваюсь с проблемами со ссылками на ObjectID.
Первоначально я наткнулся на mongoose-uuid, но, к сожалению, это не работает для моего варианта использования должным образом, потому что он перезаписывал мое явно установленное значение _id
при создании новых объектов Mongoose. Погружаясь в код плагина, он предполагает, что объект является новым (вызывая проверку значения Mongoose .isNew
) и, таким образом, переписывает _id
новым uuid. Поскольку мне нужно сохранить исходный uuid при создании новых документов в Mongo, этот плагин не работает для меня.
Затем я нашел пост Аарона Хекмана, создателя mongoose, на аналогичную тему. Это было полезно, однако сейчас я сталкиваюсь с проблемой, когда у меня не может быть, чтобы мои схемы mongoose ссылались друг на друга с помощью ObjectID, так как они технически они теперь ссылаются друг на друга, используя String '_ids.
Пример схемы:
var mongoose = require('mongoose');
var uuid = require('node-uuid');
var Schema = mongoose.Schema;
var trackPassSchema = new Schema({
_id: { type: String, default: function genUUID() {
uuid.v1()
}},
//Omitting other fields in snippet for simplicity
vehicle: [
{type: Schema.Types.ObjectId, required: true, ref: 'Vehicle'}
]
});
module.exports = mongoose.model('TrackPass', trackPassSchema);
Ссылочная схема:
var mongoose = require('mongoose');
var uuid = require('node-uuid');
var Schema = mongoose.Schema;
var vehicleSchema = new Schema({
_id: { type: String, default: function genUUID() {
uuid.v1()
}},
//Omitting other fields in snippet for simplicity
description: {type: String},
year: {type: Number}
});
module.exports = mongoose.model('Vehicle', vehicleSchema);
Когда я пытаюсь вызвать save()
trackPass, который был передан из моего приложения:
var trackPass = new TrackPass(req.body);
//Force the ID to match what was put into the request
trackPass._id = req.params.id;
trackPass.save(function (err) { ... }
Я получаю следующую ошибку:
{ [CastError: Cast to ObjectId failed for value "b205ac4d-fd96-4b1e-892a-d4fab818ea2a" at path "vehicle"]
message: 'Cast to ObjectId failed for value "b205ac4d-fd96-4b1e-892a-d4fab818ea2a" at path "vehicle"',
name: 'CastError',
type: 'ObjectId',
value: ["b205ac4d-fd96-4b1e-892a-d4fab818ea2a"],
path: 'vehicle' }
Я полагаю, что эта ошибка имеет смысл, поскольку теперь я использую строки, которые длиннее типичных идентификаторов объектов Mongo. Не имея ссылки ObjectID, я не верю, что смогу populate()
ссылаться на объекты из других коллекций. Я полагаю, что я просто не мог бы ссылаться на другие вложенные объекты в своих определениях схемы, однако мне не нравится этот подход, так как я чувствую, что потерю большую выгоду от использования ODM. Есть еще мысли?