试图用猫鼬做大量的大事.什么是最干净的方法? [英] Trying to do a bulk upsert with Mongoose. What's the cleanest way to do this?
问题描述
我有一个包含文档的集合,该文档包含三个字段:first_name,last_name和age.我试图找出猫鼬中的什么查询,我可以使用它来进行批量更新.我的应用偶尔会收到具有相同三个字段的新对象数组.我希望查询检查文档中是否已经存在名字和姓氏,如果存在,请更新年龄(如果不同).否则,如果名字和姓氏都不存在,请插入一个新文档.
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.
目前,我仅在进行导入-尚未建立此上篇文章的逻辑.
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)
})
`
我的用户模型如下:
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)
在 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()中未对此进行记录,该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 thebulkWrite(,[options],)
argument, with no effect either.GasStation.collection.bulkWrite()
. Although Mongoose bulkWrite() method claims it should be calledModel.bulkWrite()
(in this case,GasStation.bulkWrite()
), that will triggerMongoError: Unknown modifier: $__
. So,Model.collection.bulkWrite()
must be used.
另外,请注意:
You don't need to use the$set
mongo operator in theupdateOne.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 },
这篇关于试图用猫鼬做大量的大事.什么是最干净的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!