Mongoose Strict规则不接受Schema

时间:2017-09-09 23:26:59

标签: node.js mongodb mongoose

我想在Mongoose中使用update方法来更新我的MongoDB数据库。我有以下架构:

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

现在我想使用:

更新我的数据库
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
})

仅当我将strict设置为false时才有效。否则会抛出错误:

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

我理解错误是因为如果strict设置为true,Mongoose会忽略任何与Schema不匹配的额外字段。但是这种情况下,我的架构是正确的,并且字段已经到位。那为什么忽略这个呢?

1 个答案:

答案 0 :(得分:2)

您似乎在这里缺少架构设计中的几个概念。获得此类响应的唯一方法是由于数据与架构不匹配。在任何情况下,您基本上都不需要应用strict: false,除非您打算故意使用您知道与架构不匹配的项目,或者您根本不希望定义架构。通常是具有许多不同特性的饲料。

所以对于&#34;空&#34;消息,数据不匹配或您实际分配给正在使用的模型的模式不是您认为的。

明确这一点的唯一真正方法是通过示范。以下是如何做正确的事情:

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();
  }

})();

它告诉你一切都很完美:

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
    }
  ]
}

特别需要在架构选项中使用_id来注明名为id_id: false的字段。 MongoDB默认使用ObjectId,而mongoose模式默认尝试应用它。这是你特别需要关闭的东西,而不是"strict",这是&#34;蛮力&#34;应用根本没有考虑任何架构规则。这违背了定义架构的目的。