web-dev-qa-db-ja.com

ObjectID参照のためのMongooseでのUUIDの使用

CRUDスタイルのREST Mongooseを使用したNode.js、Express、MongoDBのサービスを構築しています。このサービスにより、既存のAndroid =個々のデータベースのコンテンツをオンラインでアップロード/同期するアプリケーション。

既存のアプリケーションのデータモデルは、より短い単調なMongoDBスタイルの__id_フィールドと競合する(Javaで生成された)UUIDを使用します。データモデルは既に存在し、多くのユーザーからのデータが入力されているため、ソースデータを単調なMongoDBスタイルの__id_ sに変換できません。これは私が考えることができる2つのオプションを私に残しました:1)Mongo/Mongoose(または他のODM)を単調な__id_ sの代わりに完全なUUIDでうまく再生させるか、2)monidoseにuuidフィールドを追加します__id_フィールドに加えてモデルを作成し、このアプローチの落とし穴と戦います。オプション#1を選択しようとしていますが、ObjectID参照に関する問題が発生しています。

私は最初に mongoose-uuid に遭遇しましたが、残念ながら、これは新しいMongooseオブジェクトの作成時に明示的に設定された__id_値を上書きしていたため、私のユースケースでは適切に機能していません。プラグインコードに分割すると、(Mongooseの_.isNew_値のチェックを呼び出すことによって)オブジェクトが新しいものであると想定し、__id_を新しいuuidで上書きします。 Mongoで新しいドキュメントを作成するときに元のuuidを保持する必要があるため、このプラグインは機能しません。

次に、似たようなトピックについて、マングースの作者であるアーロンヘックマンの post を見つけました。これは役に立ちましたが、マングーススキーマでObjectIDを使用して相互に参照できないという問題が発生しています。技術的には、文字列 `_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よりも長い文字列を使用しているので、このエラーは理にかなっていると思います。 ObjectID参照がないと、他のコレクションから参照されるオブジェクトをpopulate()できるとは思えません。スキーマ定義で他のネストされたオブジェクトを単に参照することはできないと思いますが、ODMを使用することの多くの利点を失うと思うので、このアプローチは好きではありません。他に何か考えはありますか?

16
JeremyL

ObjectID以外の型の__id_値でpopulate()を引き続き使用できますが、参照定義では同じ型を使用する必要があります。

したがって、trackPassSchemaを次のように変更する必要があります。

_var trackPassSchema = new Schema({
    _id: { type: String, default: function genUUID() {
        return uuid.v1()
    }},
    vehicle: [
        {type: String, required: true, ref: 'Vehicle'}
    ]
});
_

Adamがコメントで指摘しているように、default値を次のように簡略化できます。

_var trackPassSchema = new Schema({
    _id: { type: String, default: uuid.v1 },
    vehicle: [
        {type: String, required: true, ref: 'Vehicle'}
    ]
});
_
23
JohnnyHK