【问题标题】:Upsert document while pushing to array推送到数组时插入文档
【发布时间】:2016-04-17 00:52:56
【问题描述】:

我有以下架构:

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

【问题讨论】:

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


    【解决方案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' }}});
    

    【讨论】:

    • 如果我不知道字段的名称,这可以工作吗?假设我有一个名为test1Test,我不知道它有哪些非strict 字段,并且我不知道推送到数组的文档的确切结构(或者需要多少文档被推送到数组中)。
    • 可以使用mongodb的_id
    • 真的很抱歉,我很难理解。如果不是太多,你能否给我举个例子,你使用$set$push而不使用new_fieldonetwo这些词?
    • 感谢您的回答,它帮助我指明了正确的方向,并且我找到了一个非常适合我的情况的解决方案。我已经发布了我的解决方案。
    【解决方案2】:

    我已经以一种干净利落的方式解决了这个问题:

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

    我一直在寻找如何做到这一点,但我没有发现它在任何地方都得到了直接的解释,但它确实有效并且很有用。

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 2020-03-27
      • 2016-10-12
      • 2021-03-27
      • 2018-06-11
      • 1970-01-01
      • 2015-05-11
      • 2018-12-09
      • 2017-03-26
      相关资源
      最近更新 更多