尝试使用 Mongoose 进行批量更新.什么是最干净的方法来做到这一点? [英] Trying to do a bulk upsert with Mongoose. What's the cleanest way to do this?

查看:16
本文介绍了尝试使用 Mongoose 进行批量更新.什么是最干净的方法来做到这一点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含三个字段的文档的集合:first_name、last_name 和 age.我试图弄清楚我可以使用 Mongoose 中的什么查询来进行批量更新插入.我的应用程序偶尔会收到具有相同三个字段的新对象数组.我希望查询检查文档中是否已经存在第一个和姓氏,如果存在 - 如果年龄不同,则更新年龄.否则,如果名字和姓氏不存在,则插入一个新文档.

I have a collection that holds documents that contains three fields: first_name, last_name, and age. I'm trying to figure out what query in Mongoose I can use to do a bulk upsert. My app is occasionally receiving a new array of objects with those same three fields. I want the query to check if the first AND last name already exist within a document, and if they do - update the age if it's different. Otherwise, if the first and last name don't exist, insert a new document.

目前,我只做导入 - 还没有构建这个 upsert 片段的逻辑.

Currently, I'm only doing the import - and haven't yet built out the logic for this upsert piece.

app.post('/users/import', function(req, res) {
  let data = req.body;
  let dataArray = [];
  data.forEach(datum => {
    dataArray.push({
        first: datum.first,
        last: datum.last,
        age: datum.age
    })
})

User.insertMany(dataArray, answer => {
    console.log(`Data Inserted:`,answer)
})

`

我的用户模型如下所示:

And my User model looks like this:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const userSchema = new Schema({
  first: String,
  last: String,
  age: Number,
  created_at: { type: Date, default: Date.now }
});

var User = mongoose.model('User', userSchema);
module.exports = User;

推荐答案

(mongoose@4.9.1, mongodb@3.4.2)

TL;DR

await GasStation.collection.bulkWrite([ // <<==== use the model name
  {
    'updateOne': {
      'filter': { 'id': '<some id>' },
      'update': { '$set': { /* properties to update */ } },
      'upsert': true,  // <<==== upsert in every document
    }
  },
  /* other operations here... */
]);

长话:

在努力解决 Mongoose API 糟糕的文档之后,我解决了批量更新插入 调整 bulkWrite() 方法中的 updateOne:{} 操作.

After struggling with Mongoose API poor documentation, I solved the bulk upsert tweaking updateOne:{} operation in the bulkWrite() method.

需要考虑的一些未记录的事情:

A couple of undocumented things to consider:

// suppose:
var GasStation = mongoose.model('gasstation', gasStationsSchema);
var bulkOps = [ ];

// for ( ... each gasStation to upsert ...) {
  let gasStation = { country:'a', localId:'b', xyz:'c' };
  // [populate gasStation as needed]
  // Each document should look like this: (note the 'upsert': true)
  let upsertDoc = {
    'updateOne': {
      'filter': { 'country': gasStation.country, 'localId': gasStation.localId },
      'update': gasStation,
      'upsert': true
  }};
  bulkOps.push(upsertDoc);
// end for loop

// now bulkWrite (note the use of 'Model.collection')
GasStation.collection.bulkWrite(bulkOps)
  .then( bulkWriteOpResult => {
    console.log('BULK update OK');
    console.log(JSON.stringify(bulkWriteOpResult, null, 2));
  })
  .catch( err => {
    console.log('BULK update error');
    console.log(JSON.stringify(err, null, 2));
  });

这里的两个关键问题是不完整的 API 文档问题(至少在撰写本文时):

The two key things here are incomplete API documentation issues (at the time of writing, at least):

  • 'upsert': true 在每个文档中.这在 Mongoose API () 中没有记录,通常指的是 node-mongodb-native 驱动程序.查看这个驱动程序中的updateOne,你可以想添加 'options':{'upsert': true},但是,不……那不行.我还尝试将这两种情况添加到 bulkWrite(,[options],) 参数中,但也没有任何效果.
  • GasStation.collection.bulkWrite().尽管 Mongoose bulkWrite() 方法 声称它应该被称为 Model.bulkWrite()(在本例中为 GasStation.bulkWrite()),这将触发 MongoError: Unknown modifier: $__.因此,必须使用 Model.collection.bulkWrite().
  • 'upsert': true in each document. This is not documented in Mongoose API (), which often refers to node-mongodb-native driver. Looking at updateOne in this driver, you could think to add 'options':{'upsert': true}, but, no... that won't do. I also tried to add both cases to the bulkWrite(,[options],) argument, with no effect either.
  • GasStation.collection.bulkWrite(). Although Mongoose bulkWrite() method claims it should be called Model.bulkWrite() (in this case, GasStation.bulkWrite()), that will trigger MongoError: Unknown modifier: $__. So, Model.collection.bulkWrite() must be used.

另外,请注意:

  • 您不需要在 updateOne.update 字段中使用 $set mongo 运算符,因为 mongoose 会在 upsert 的情况下处理它(请参阅 bulkWrite() 示例中的注释).
  • 请注意,我在架构中的唯一索引(需要 upsert 正常工作)定义为:
  • You don't need to use the $set mongo operator in the updateOne.update field, since mongoose handles it in case of upsert (see bulkWrite() comments in example).
  • Note that my unique index in the schema (needed for upsert to work properly) is defined as:

gasStationsSchema.index({ country: 1, localId: 1 }, { unique: true });

希望有帮助.

==>(猫鼬 5?)

正如@JustinSmith 所注意到的,Mongoose 添加的 $set 操作符似乎不再起作用了.也许是因为猫鼬 5?

As noticed by @JustinSmith, the $set operator added by Mongoose doesn't seem to be working anymore. Maybe it's because of Mongoose 5?

在任何情况下,明确使用 $set 应该这样做:

In any case, using $set explicitly should do:

'update': { '$set': gasStation },

这篇关于尝试使用 Mongoose 进行批量更新.什么是最干净的方法来做到这一点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆