我有以下架构:
var TestSchema = db.Schema({
name: { type: String, required: true, unique: true }
data: []
},
{ strict: false });
var Test = db.model('Test', TestSchema);
注意它是strict: false
。我希望能够upsert
新文件。问题是,我不希望覆盖data
数组,而是要将新文档推入其中。
例如,假设这是一个现有文档:
{ name: "hello world",
data:
[ { one: '123',
two: '456' } ]
}
我希望upsert
这个:
{ name: "hello world",
new_field: "to be updated"
data:
[ { one: 'pushed to the array',
two: 'xyz' } ]
}
预期结果将是:
{ name: "hello world",
new_field: "to be updated"
data:
[ { one: 'abc',
two: 'xyz' },
{ one: 'pushed to the array',
two: 'xyz'} ]
}
要明确说明:文档已经存在,所以应该更新。新字段new_field
已更新。但是,我们不是覆盖现有的data
数组(作为常规更新),而是将新文档推送到数组中。
我有一个非常难看的工作版本,使用三个调用来实现这一点,这是完全无法使用的(异步 - >重复插入而不是在同时抛出许多查询时更新)。
这实际上可以在Mongoose中实现吗?
答案 0 :(得分:1)
您可以像这样使用$ push:
{$set:{ new_field: "to be updated" },$push:{data:{ one: 'pushed to the array',two: 'xyz' }}}
更新查询将是:
db.test.update({name: "hello world"}, {
$set:{ new_field: "to be updated" }
$push:{data:{ one: 'pushed to the array',two: 'xyz' }}});
答案 1 :(得分:0)
我以一种干净利落的方式解决了这个问题:
// Let 'test' be a Test object who's values we want to upsert
test = {
name: "hello world",
new_field: "to be updated"
data:
[ { one: 'pushed to the array',
two: 'xyz' } ]
}
// We do this to 'test'
test['$addToSet'] = {
'data': { '$each': test.data }
};
delete test.data
// 'test' now looks like this
// test = {
// 'name': 'hello world',
// 'new_field': 'to be updated'
// '$addToSet': { data: { '$each': [Object] } }
// }
// And this is how we upsert 'test'
// while also upserting values into the data array
Test.findOneAndUpdate({
name: test.name,
}, test, { upsert: true, new: true }, function(error, doc) {
console.log(doc);
});
我一直在寻找如何做到这一点,并且我没有在任何地方直接解释它,但它有效并且它很有用。