Javascript 在遍历游标和更新文档时,应用程序错误关闭了连接
我有一个简单的node.js应用程序,它通过查询创建光标,然后根据城市和温度对采集的数据进行排序。之后,我遍历游标并通过添加highest:true来更新每个城市温度最高的文档Javascript 在遍历游标和更新文档时,应用程序错误关闭了连接,javascript,node.js,mongodb,mongodb-query,Javascript,Node.js,Mongodb,Mongodb Query,我有一个简单的node.js应用程序,它通过查询创建光标,然后根据城市和温度对采集的数据进行排序。之后,我遍历游标并通过添加highest:true来更新每个城市温度最高的文档 var MongoClient = require('mongodb').MongoClient; MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) { if(err) throw err; var curs
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
console.dir("Closing database connection");
return db.close();
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
});
}
});
});
这里的问题是,只有第一个城市得到了正确更新,以下是输出:
“柏林是81;”已成功更新:1“”巴黎-佛罗里达州为83;'
“华沙新墨西哥州57岁;”巴塞罗那佛蒙特州57岁结束
数据库连接“”错误:{[MongoError:连接已由关闭
应用程序]名称:'MongoError'}错误:{[MongoError:连接
由应用程序关闭]名称:'MongoError'}错误:{[MongoError:
由应用程序关闭的连接]名称:'MongoError'}
我对正在发生的事情的猜测是:光标会遍历所有文档,并在温度最高的文档上调用更新:
db.collection('data').update(query, operator, function(err, updated)
但在回调返回之前,游标完成迭代,调用此代码片段以关闭连接:
if(doc == null) {
console.dir("Closing database connection");
return db.close();
}
之后,所有未完成处理的更新都将出错,因为没有可用的db连接
处理它的正确方法是什么,这样只有在所有文档都成功更新后,连接才会关闭?我通常认为对于迭代器来说,接口是一个更好的选择。游标对象上有一个用于此的方法:
var stream = db.collection('data').find().sort(
{ City : 1, Temperature : -1 }
).stream();
stream.on('data',function(data) {
// do things with current document
// but pause on things with a callback then resume;
stream.pause();
db.collection('data').update(query, operator, function(err, updated) {
// resume the stream when this callback is done
stream.resume();
})
});
stream.on('end',function() {
// Called when everything is complete
// db.close is safe here as long as you are no longer using the connection
db.close();
});
事实上,从本机驱动程序的角度来看,流接口是默认游标对象的一部分
但通常,对于一次性处理脚本,只能调用db.close()
。通常,在服务器类型的实现中根本不应该调用它,而应该在整个生命周期中保持连接的打开状态。我通常认为接口是迭代器的更好选择。游标对象上有一个用于此的方法:
var stream = db.collection('data').find().sort(
{ City : 1, Temperature : -1 }
).stream();
stream.on('data',function(data) {
// do things with current document
// but pause on things with a callback then resume;
stream.pause();
db.collection('data').update(query, operator, function(err, updated) {
// resume the stream when this callback is done
stream.resume();
})
});
stream.on('end',function() {
// Called when everything is complete
// db.close is safe here as long as you are no longer using the connection
db.close();
});
事实上,从本机驱动程序的角度来看,流接口是默认游标对象的一部分
但通常,对于一次性处理脚本,只能调用db.close()
。通常,在服务器类型的实现中根本不应该调用它,而应该在整个生命周期中保持连接的打开状态。我通常认为接口是迭代器的更好选择。游标对象上有一个用于此的方法:
var stream = db.collection('data').find().sort(
{ City : 1, Temperature : -1 }
).stream();
stream.on('data',function(data) {
// do things with current document
// but pause on things with a callback then resume;
stream.pause();
db.collection('data').update(query, operator, function(err, updated) {
// resume the stream when this callback is done
stream.resume();
})
});
stream.on('end',function() {
// Called when everything is complete
// db.close is safe here as long as you are no longer using the connection
db.close();
});
事实上,从本机驱动程序的角度来看,流接口是默认游标对象的一部分
但通常,对于一次性处理脚本,只能调用db.close()
。通常,在服务器类型的实现中根本不应该调用它,而应该在整个生命周期中保持连接的打开状态。我通常认为接口是迭代器的更好选择。游标对象上有一个用于此的方法:
var stream = db.collection('data').find().sort(
{ City : 1, Temperature : -1 }
).stream();
stream.on('data',function(data) {
// do things with current document
// but pause on things with a callback then resume;
stream.pause();
db.collection('data').update(query, operator, function(err, updated) {
// resume the stream when this callback is done
stream.resume();
})
});
stream.on('end',function() {
// Called when everything is complete
// db.close is safe here as long as you are no longer using the connection
db.close();
});
事实上,从本机驱动程序的角度来看,流接口是默认游标对象的一部分
但通常,对于一次性处理脚本,只能调用
db.close()
。通常情况下,在服务器类型实现中根本不应该调用它,而应该在整个生命周期中保持连接打开状态。正如Neil提到的,我们可以使用.stream(),但我能够通过计算已处理的更新并在所有我们希望更新的文档更新后关闭db连接,使程序按预期执行。
在我的例子中,这非常简单,因为我的数据库中只有4个城市,所以我只希望更新4个文档。我们也可以通过查询和计数结果获得这个数字,但这对我来说已经足够好了
以下是工作代码:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
var updatedCount = 0;
var expectedToUpdate = 4; // Hardcoded, but we might want to obtain it pragmatically
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
return
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
updatedCount++;
if (updatedCount == expectedToUpdate) {
console.dir("updated expected number of documents. Closing db.");
db.close();
}
});
}
});
});
正如Neil提到的,我们可以使用.stream(),但我能够通过计算已处理的更新并在所有我们希望更新的文档更新后关闭db连接,使程序按预期执行。 在我的例子中,这非常简单,因为我的数据库中只有4个城市,所以我只希望更新4个文档。我们也可以通过查询和计数结果获得这个数字,但这对我来说已经足够好了 以下是工作代码:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
var updatedCount = 0;
var expectedToUpdate = 4; // Hardcoded, but we might want to obtain it pragmatically
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
return
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
updatedCount++;
if (updatedCount == expectedToUpdate) {
console.dir("updated expected number of documents. Closing db.");
db.close();
}
});
}
});
});
正如Neil提到的,我们可以使用.stream(),但我能够通过计算已处理的更新并在所有我们希望更新的文档更新后关闭db连接,使程序按预期执行。 在我的例子中,这非常简单,因为我的数据库中只有4个城市,所以我只希望更新4个文档。我们也可以通过查询和计数结果获得这个数字,但这对我来说已经足够好了 以下是工作代码:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
var updatedCount = 0;
var expectedToUpdate = 4; // Hardcoded, but we might want to obtain it pragmatically
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
return
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
updatedCount++;
if (updatedCount == expectedToUpdate) {
console.dir("updated expected number of documents. Closing db.");
db.close();
}
});
}
});
});
正如Neil提到的,我们可以使用.stream(),但我能够通过计算已处理的更新并在所有我们希望更新的文档更新后关闭db连接,使程序按预期执行。 在我的例子中,这非常简单,因为我的数据库中只有4个城市,所以我只希望更新4个文档。我们也可以通过查询和计数结果获得这个数字,但这对我来说已经足够好了 以下是工作代码:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017/temp', function(err, db) {
if(err) throw err;
var cursor = db.collection('data').find().sort( { City : 1, Temperature : -1 } );
var previous = '';
var updatedCount = 0;
var expectedToUpdate = 4; // Hardcoded, but we might want to obtain it pragmatically
cursor.each(function(err, doc) {
if(err) throw err;
if(doc == null) {
return
}
if (previous != doc.City) {
previous = doc.City;
var query = { _id : doc._id };
var operator = { '$set' : { highest : true } };
console.dir(doc.City + " is " + doc.Temperature + "; ");
db.collection('data').update(query, operator, function(err, updated) {
if(err) {
console.error('Error:', err);
throw err;
}
console.dir("Successfully updated: " + JSON.stringify(updated));
updatedCount++;
if (updatedCount == expectedToUpdate) {
console.dir("updated expected number of documents. Closing db.");
db.close();
}
});
}
});
});