2016-04-06 5 views
1

ユーザーがさまざまな種類のカスタムフィールドを作成できるアプリケーションを作成しています。これらのフィールドをmongoに保存したいと思います。タイプには、String、Number、およびDateが含まれます。私のスキーマは次のようになります:Mongoose日付が混在した型フィールド

const MetaSchema = new mongoose.Schema({ 
    key: String, 
    value: {type: mongoose.Schema.Types.Mixed}, 
    type: String, 
    created_at: {type: Date, default: Date.now} 
}); 

これはうまく動作し、私は期待どおりのデータを保存することができます。

{ 
    "key": "Contract Signed", 
    "value": "2016-04-06T22:35:11.540Z", 
    "type": "date" 
} 

私はモンゴ/マングースは、治療のために取得することができます任意の方法と:私は、のように見えるかもしれないペイロードをISO形式でサーバに渡って送信されるインスタンスの日付を、保存したい場合に問題があり、文字列の代わりに日付のように保存しますか?これをタイプ・デートに設定すると、トリックを行うと思うが、カスタム・フィールドのために思いつくものはすべて保存しなければならない。本当にありがとう!

TLDR:挿入されるデータのタイプ(IE DateとString)に基づいて、mongoose/mongoの混合データ型を異なる方法で扱うことができます。

+1

これを処理するより良い方法は[discriminators](http://mongoosejs.com/docs/discriminators.html)です。これは本質的に各オブジェクトをバインドさせる独自の "タイプ"(デフォルトは '__t')を実装しますそれ自身の擬似モデルであり、それ自身のスキーマです。次に、各 "タイプ"に対して "厳密な"処理を行うことができます。これは、「混合」を使用する場所で検証ロジックを手作業で行うよりもはるかに優れています。 –

+0

ありがとう@NeilLunn!これは私の必要と同じように見えます。私が受け入れることができる応答を提出してインターネットポイントを増やしたいのですか? :) ありがとうございました! – Greg

答えて

2

マングースを使用すると、おそらくここに行くことができます。discriminators実際には、格納されたドキュメント内の独自の "タイプ"(デフォルトでは、__tのプロパティ)で動作します。これにより、マングースは、それぞれのオブジェクトに独自の添付されたスキーマを持つ一種の "モデル"を実際に適用できます。簡単な例として

:これらは基本的にしているので、だから、「関連」

var async = require('async'), 
    util = require('util'), 
    mongoose = require('mongoose'), 
    Schema = mongoose.Schema; 

mongoose.connect('mongodb://localhost/things'); 
mongoose.set("debug",true); 

function BaseSchema() { 

    Schema.apply(this,arguments); 

    this.add({ 
    key: String, 
    created_at: { type: Date, default: Date.now } 
    }); 

} 

util.inherits(BaseSchema,Schema); 

var metaSchema = new BaseSchema(); 

var stringSchema = new BaseSchema({ 
    value: String 
}); 

var numberSchema = new BaseSchema({ 
    value: Number 
}); 

var dateSchema = new BaseSchema({ 
    value: Date 
}); 

var MetaModel = mongoose.model('MetaModel',metaSchema), 
    StringModel = MetaModel.discriminator('StringModel', stringSchema), 
    NumberModel = MetaModel.discriminator('NumberModel', numberSchema), 
    DateModel = MetaModel.discriminator('DateModel', dateSchema); 

async.series(
    [ 
    function(callback) { 
     MetaModel.remove({},callback); 
    }, 
    function(callback) { 
     async.each(
     [ 
      { "model": "StringModel", "value": "Hello" }, 
      { "model": "NumberModel", "value": 12 }, 
      { "model": "DateModel", "value": new Date() } 
     ], 
     function(item,callback) { 
      mongoose.model(item.model).create(item,callback) 
     }, 
     callback 
    ); 
    }, 
    function(callback) { 
     MetaModel.find().exec(function(err,docs) { 
     console.log(docs); 
     callback(err); 
     }); 
    }, 
    function(callback) { 
     DateModel.findOne().exec(function(err,doc) { 
     console.log(doc); 
     callback(err); 
     }); 
    } 
    ], 
    function(err) { 
    if (err) throw err; 
    mongoose.disconnect(); 
    } 
) 

は、私は、共通の要素を持つ「ベース」スキーマを定義しています。もちろん、それぞれの "タイプ"ごとに別々のスキーマがあります。コア「モ​​デル」への実際の割り当ては、これらの行で発生します:

var MetaModel = mongoose.model('MetaModel',metaSchema), 
    StringModel = MetaModel.discriminator('StringModel', stringSchema), 
    NumberModel = MetaModel.discriminator('NumberModel', numberSchema), 
    DateModel = MetaModel.discriminator('DateModel', dateSchema); 

これはMetaModelが実際に収集し、「デフォルト」のスキーマのassingmentを定義することを意味します。次の行は、同じコレクションに格納されるドキュメントの他の "タイプ"を定義するために、そのモデルの.discriminator()を使用しています。参照するときしかし、あなたはそのすべてがメインモデルに割り当てられmetamodelsコレクションに作成されて見ることができます

Mongoose: metamodels.remove({}) {} 
Mongoose: metamodels.insert({ value: 'Hello', __t: 'StringModel', created_at: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), _id: ObjectId("5705a8a8443c0f74491bdec0"), __v: 0 }) 
Mongoose: metamodels.insert({ value: 12, __t: 'NumberModel', created_at: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), _id: ObjectId("5705a8a8443c0f74491bdec1"), __v: 0 }) 
Mongoose: metamodels.insert({ value: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), __t: 'DateModel', created_at: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), _id: ObjectId("5705a8a8443c0f74491bdec2"), __v: 0 }) 
Mongoose: metamodels.find({}) { fields: undefined } 
[ { created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST), 
    __t: 'StringModel', 
    __v: 0, 
    value: 'Hello', 
    _id: 5705a8a8443c0f74491bdec0 }, 
    { created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST), 
    __t: 'NumberModel', 
    __v: 0, 
    value: 12, 
    _id: 5705a8a8443c0f74491bdec1 }, 
    { created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST), 
    __t: 'DateModel', 
    __v: 0, 
    value: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST), 
    _id: 5705a8a8443c0f74491bdec2 } ] 
Mongoose: metamodels.findOne({ __t: 'DateModel' }) { fields: undefined } 
{ created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST), 
    __t: 'DateModel', 
    __v: 0, 
    value: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST), 
    _id: 5705a8a8443c0f74491bdec2 } 

:何が起こっているかを示すために上のデバッグ出力で

は、そのリストは、このような何かを作り出します各「識別器モデル」には、モデル名を含む__tフィールドが自動的に作成されます。これは後でデータを読み込む際に使用され、mongooseはオブジェクトをキャストするときに適用するモデルとアタッチされたスキーマを認識します。

これらはすべて独自のスキーマを持つため、標準の検証ルールが適用されます。さらに、各タイプのスキーマに付加された「インスタンスメソッド」も、別個のモデルと同じように適用されます。

最後に、その__tフィールドは、クエリや更新などの他の操作に「ディスクリミネータモデル」の1つを使用して適用されます。

 DateModel.findOne().exec(function(err,doc) { 
     console.log(doc); 
     callback(err); 
     }); 

そして、実際の呼び出し:最後に実行されたステートメントに示すように

Mongoose: metamodels.findOne({ __t: 'DateModel' }) { fields: undefined } 

プロパティの値は、「タイプ」を示し、収集データの「仮想ビュー」を与えるために自動的に含まれていることまるでその特定のタイプだけを含んでいるかのように。

実際のパワーは、同じコレクション内のすべてのオブジェクトにあり、マングースがデータの取得時に自動的に「クラスタイプ」を割り当てることができます。

+0

私は今までstackoverflowで得た最も包括的な答えの一つDude。時間をいただきありがとうございます!とても有難い! – Greg

関連する問題