在推入数组时向上插入文档

我有以下架构:

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数组(作为常规更新),而是将新文档推送到数组中。

我有一个非常丑陋的工作版本,使用三个调用来实现这一点,这是完全不可用(asynchronous – >重复获取插入,而不是更新,当你同时抛出许多查询)。

这实际上可以在mongoose中实现吗?

你可以像这样使用$ 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' }}}); 

我已经用一个很好和干净的方式解决了这个问题:

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

我一直在寻找如何做到这一点,我没有find它直接解释任何地方,但它的作品,它是有用的。