2017-09-09 14 views
0

私のMongoDBデータベースを更新するためにMongooseでupdateメソッドを使いたいと思います。私は、次のスキーマを持っている:Mongoose Strictルールはスキーマを受け付けません

let queryOptions = { 
    upsert: true, 
    setDefaultsOnInsert: true, 
    strict: true 
} 
let queryFields = { 
    $addToSet : { 
    data_hourly : { 
     id: 12345 
    } 
    } 
} 
Data.update({ _id: my._id}, 
    queryFields, queryOptions, 
    err => { 
    if (err) throw err 
}) 

を私はfalsestrictを設定している場合のみ機能:

let DataSchema = new mongoose.Schema({ 
    _id: Number, 
    data_hourly: [{ 
    id: Number 
    }] 

は今、私は使用して私のDBを更新したいです。私はマングースは厳しいがtrueに設定されている場合は、スキーマと一致してはいけない余分なフィールドを無視するため、エラーがあることを理解

MongoError: '$addToSet' is empty. You must specify a field like so: {$addToSet: {<field>: ...}} 

:それ以外の場合は、エラーがスローされます。しかし、この場合、私のスキーマは正しいですし、フィールドは適切です。では、なぜこれを無視しているのですか?

+0

実際には 'timestamp'には何がありますか?おそらく、配列を追加しようとしているのだろうか、それとも単なる値でなければならないときは、少なくともある種のオブジェクトであるかのように思えます。 –

+0

タイムスタンプは生成されたintです。 12345 – Chris

+0

何によって生成されますか?コードを表示します。削除される理由は、スキーマの必須タイプと一致しないためです。それが私の言うことです。それを自分で処理できない場合は、入力がどこから来ているのかを確認する必要があります。 –

答えて

1

ここでスキーマ設計にいくつかの概念が欠けているようです。このような応答を得る唯一の方法は、データからスキーマへの不一致によるものです。どんな場合でも、スキーマと一致しないことを知っているアイテムを意図的に使用する意図がないか、スキーマをまったく定義したくない場合は、基本的にはstrict: falseを適用する必要はありません。通常、さまざまな特性を持つフィード。

"空の"メッセージの場合、データが一致しないか、使用しているモデルに実際に割り当てられているスキーマが、あなたの考えではありません。

これを明確にする唯一の実際の方法は、デモンストレーションです。ここでは適切に行われ、あなたがしようとしている何をする方法は次のとおりです。

const mongoose = require('mongoose'), 
     Schema = mongoose.Schema; 

mongoose.Promise = global.Promise; 
mongoose.set('debug',true); 

const uri = 'mongodb://localhost/test', 
     options = { useMongoClient: true }; 

const hourlySchema = new Schema({ 
    id: Number 
},{ _id: false }); 

const dataSchema = new Schema({ 
    _id: Number, 
    data_hourly: [hourlySchema] 
},{ _id: false }); 

const Data = mongoose.model('Data', dataSchema); 

function log(data) { 
    console.log(JSON.stringify(data,undefined,2)) 
} 

(async function() { 

    try { 

    const conn = await mongoose.connect(uri,options); 

    await Promise.all(
     Object.keys(conn.models).map(m => conn.models[m].remove()) 
    ); 


    let data = [ 
     { _id: 12345, data_hourly: 12345 }, 
     { _id: 12345, data_hourly: 98765 }, 
     { _id: 12345, data_hourly: 98765 } 
    ]; 

    for (let item of data) { 

     let doc = await Data.findByIdAndUpdate(item._id, 
     { $addToSet: { data_hourly: { id: item.data_hourly } } }, 
     { new: true, upsert: true } 
    ); 

     log(doc); 
    } 


    } catch(e) { 
    console.error(e); 
    } finally { 
    mongoose.disconnect(); 
    } 

})(); 

すべてが完璧に動作することを示している:中_id: falseに出席することが特に必要としている_idまたはidという名前

Mongoose: datas.remove({}, {}) 
Mongoose: datas.findAndModify({ _id: 12345 }, [], { '$setOnInsert': { __v: 0 }, '$addToSet': { data_hourly: { id: 12345 } } }, { new: true, upsert: true, remove: false, fields: {} }) 
{ 
    "_id": 12345, 
    "__v": 0, 
    "data_hourly": [ 
    { 
     "id": 12345 
    } 
    ] 
} 
Mongoose: datas.findAndModify({ _id: 12345 }, [], { '$setOnInsert': { __v: 0 }, '$addToSet': { data_hourly: { id: 98765 } } }, { new: true, upsert: true, remove: false, fields: {} }) 
{ 
    "_id": 12345, 
    "__v": 0, 
    "data_hourly": [ 
    { 
     "id": 12345 
    }, 
    { 
     "id": 98765 
    } 
    ] 
} 
Mongoose: datas.findAndModify({ _id: 12345 }, [], { '$setOnInsert': { __v: 0 }, '$addToSet': { data_hourly: { id: 98765 } } }, { new: true, upsert: true, remove: false, fields: {} }) 
{ 
    "_id": 12345, 
    "__v": 0, 
    "data_hourly": [ 
    { 
     "id": 12345 
    }, 
    { 
     "id": 98765 
    } 
    ] 
} 

フィールドをスキーマオプションMongoDBはデフォルトでObjectIdを使用し、mongooseスキーマはこれをデフォルトで適用しようとします。 "strict"の代わりにオフにする必要があるのは、スキーマルールがまったく考慮されていないことを「ブルートフォース」に適用することです。スキーマが定義されているという目的を破るものです。

+0

この回答をお寄せいただきありがとうございます。間接的に{strict: 'throw'}を使用して問題を見つけるのを助けました。それは単純にタイプの不一致でした。 Mongooseによって与えられた最初のエラーは、トラブルシューティングに全く役立たなかった!再度、感謝します – Chris

関連する問題