使用Mongoose甚至Mongo可能会出现类似的情况吗?
Center.update({ghostBuster:{$exists}},{$set:{ectoplasm: this.exoplasm},$unset: {exoplasm:""}}, function(err, result){ })
我想更新一些记录并将一个字段移动到另一个字段,所以如果我可以在更新它时引用该获取的记录。在这种情况下,我将ectoplasm
字段的值设为exoplasm
是否可以在没有在Mongoose Schema上定义钩子的情况下执行此操作?
答案 0 :(得分:0)
使用mongo,您可以通过迭代从查询查询返回的游标(使用forEach()
方法)并在循环内更新集合来完成此操作。例如:
db.centers.find({
"ghostBuster": { "$exists": true }
}).forEach(function(doc){
db.centers.update(
{ "_id": doc._id },
{
"$set": { "ectoplasm": doc.exoplasm },
"$unset": { "exoplasm": "" }
}
)
});
这"来回"到服务器将花费IO,所以你会尝试最小化它。使用 bulkWrite()
方法(如果使用MongoDB版本3.2)批量执行更新:
var ops = [];
db.centers.find({
"ghostBuster": { "$exists": true }
}).forEach(function(doc) {
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { "ectoplasm": doc.exoplasm },
"$unset": { "exoplasm": "" }
}
}
});
if (ops.length === 1000) {
db.centers.bulkWrite(ops);
ops = [];
}
})
if (ops.length > 0) db.centers.bulkWrite(ops);
或者对于MongoDB 2.6.x和3.0.x版本,请使用此版本的 Bulk operations :
var bulk = db.centers.initializeUnorderedBulkOp(),
counter = 0;
db.centers.find({
"ghostBuster": { "$exists": true }
}).forEach(function(doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "ectoplasm": doc.exoplasm },
"$unset": { "exoplasm": "" }
});
if (counter % 1000 === 0) {
bulk.execute();
bulk = db.centers.initializeUnorderedBulkOp();
}
});
if (counter % 1000 !== 0 ) bulk.execute();
两种情况下的批量操作API都有助于减少服务器上的IO负载,方法是在集合中的每1000个文档中只发送一次请求进行处理。
对于Mongoose等价物,您可以实现类似下面的内容,使用Promises来处理node.js中批量API的异步性质。
要使用基础批量操作API,您应该通过mongoose模型中的.collection
属性访问它。在使用API之前,请等待mongoose成功连接到db,因为Mongoose还没有真正支持"initializeOrderedBulkOp()"
功能,因为它不能与mongoose的内部缓冲系统一起使用。
var mongoose = require('mongoose'),
express = require('express'),
Promise = require('bluebird'),
Schema = mongoose.Schema;
function connect(uri, options){
return new Promise(function(resolve, reject){
mongoose.connect(uri, options, function(err){
if (err) return reject(err);
resolve(mongoose.connection);
});
});
}
var centerSchema = new Schema({
exoplasm: Number,
ghostBuster: Number,
time: Date
}, { collection: "centers" });
var Center = mongoose.model("Center", centerSchema);
/*
function bulkUpdate(Model){
return new Promise(function(resolve, reject){
var bulk = Model.collection.initializeUnorderedBulkOp(),
counter = 0;
Model.find({ "ghostBuster" : { "$exists": true } })
.lean().exec(function (err, docs) {
if (err) return reject(err);
docs.forEach(function (doc){
counter++;
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "ectoplasm": doc.exoplasm },
"$unset": { "exoplasm": "" }
});
if (counter % 500 == 0 ) {
bulk.execute(function(err, result) {
if (err) return reject(err);
bulk = Model.collection.initializeUnorderedBulkOp();
resolve(result);
});
}
});
if (counter % 500 != 0 ) {
bulkUpdateOps.execute(function(err, result) {
if (err) return reject(err);
resolve(result);
});
}
});
});
}
*/
function bulkUpdate(Model){
return new Promise(function(resolve, reject){
var ops = [],
collection = Model.collection;
Model.find({ "ghostBuster" : { "$exists": true } })
.lean().exec(function (err, docs) {
if (err) return reject(err);
docs.forEach(function (doc){
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { "ectoplasm": doc.exoplasm },
"$unset": { "exoplasm": "" }
}
}
});
if (ops.length === 1000) {
collection.bulkWrite(ops, function(err, result) {
if (err) return reject(err);
ops = [];
resolve(result);
});
}
});
if (ops.length > 0) {
collection.bulkWrite(ops, function(err, result) {
if (err) return reject(err);
resolve(result);
});
}
});
});
}
connect('mongodb://localhost/test', {}).then(function(db){
bulkUpdate(Center).then(function(res){
console.log('Bulk update complete.', res);
}, function(err){
console.log('Bulk Error:', err);
db.close();
});
}, function(err){
console.log('DB Error:', err);
});