我想在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不匹配的额外字段。但是这种情况下,我的架构是正确的,并且字段已经到位。那为什么忽略这个呢?
答案 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;应用根本没有考虑任何架构规则。这违背了定义架构的目的。