推送到阵列

时间:2016-01-12 11:59:49

标签: javascript node.js mongodb mongoose mean-stack

我有以下架构:

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中实现吗?

2 个答案:

答案 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);
});

我一直在寻找如何做到这一点,并且我没有在任何地方直接解释它,但它有效并且它很有用。