db.bind('tag', {
inc: function(name) {
console.log('function inc');
this.update({name: name}, {'$inc': {count: 1}}, {upsert: true}, function() {
console.log('inc callback');
});
},
dec: function(name) {
console.log('function dec');
var self = this;
self.update({name: name}, {'$inc': {count: -1}}, {upsert: true}, function() {
console.log('function dec callback');
self.findOne({name: name}, function(error, item){
if (item && item.count <= 0) {
self.remove(item);
}
})
});
},
all: function(callback) {
console.log('function all');
this.find().toArray(callback);
}
});
for (var i = 0; i < 1000; i++) {
db.tag.inc('电影');
}
for (var i = 0; i < 500; i++) {
db.tag.dec('电影');
}
db.tag.all(function(err, data) {
console.log('function all callback');
for (var index in data) {
console.dir(data);
}
})
多运行几次,看输出。会发现所有的操作是串行的。不知道是因为mongo native的驱动本身就是串行的还是因为mongoskin在处理的时候串行的。
为了测试是不是因为mongo native驱动的问题,然后用mongoose写了一个另外类似功能的代码,如下:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TagSchema = new Schema({
name : { type: String, index: true },
count : { type: Number },
});
TagSchema.statics.inc = function(name) {
console.log('function inc');
this.update({name: name}, {'$inc': {count: 1}}, {upsert: true}, function() {
console.log('function inc callback!');
});
}
TagSchema.statics.dec = function(name) {
console.log('function dec');
var self = this;
self.update({name: name}, {'$inc': {count: -1}}, {upsert: true}, function(error) {
console.log('function dec callback');
if (error) {
return;
}
self.findOne({name: name}, function(error, item) {
if (error) {
return;
}
if (item && item.count <= 0) {
item.remove();
}
});
});
}
TagSchema.statics.all = function(callback) {
console.log('function all');
this.find().desc('count').exec(callback);
}
var Tag = mongoose.model('Tag', TagSchema);
mongoose.connect('mongodb://localhost/testdb2');
for (var i = 0; i < 1000; i++) {
Tag.inc('电影');
}
for (var i = 0; i < 500; i++) {
Tag.dec('电影');
}
Tag.all(function(err, data) {
console.log('function all callback');
for (var index in data) {
console.dir(data);
}
})
任然是运行看结果。你会发现,mongoose不是串行的。
代码解释:
先看第一个for循环:
for (var i = 0; i < 1000; i++) {
db.tag.inc('电影');
}
这里db.tag.inc会直接调用函数
inc: function(name) {
console.log('function inc');
this.update({name: name}, {'$inc': {count: 1}}, {upsert: true}, function() {
console.log('inc callback');
});
},
直接的函数调用,不存在异步,所以函数里面的
console.log('function inc');
会在for里面输出.在输出之后,会执行函数里面的代码:
this.update({name: name}, {'$inc': {count: 1}}, {upsert: true}, function() {
console.log('inc callback');
});
注意,下面这条语句是异步函数里面的语句:
console.log('inc callback');
这条异步语句,会在数据库返回结果后执行。整个文件的其他代码类似
所以连起来整个文件的代码应该输出:
1000次 function inc
1000次 function dec
1次 function all
然后会输出
1000次 function inc callback
1000次 function dec callback
1次 function all callback
那么问题就出现了。在mongoskin里面会按照上面的顺序输出。而在mongoose里面会顺序输出:
1000次 function inc
1000次 function dec
1次 function all
这个是应该的,因为不存在异步。但是会乱序输出:
1000次 function inc callback
1000次 function dec callback
1次 function all callback
说明他的回调函数,是异步返回的,根据该语句的执行时间不同,返回的顺序不一样。
所以我上面的所有代码说明了,在异步回调函数的返回顺序这个问题上,mongoskin是顺序的,mongoose是乱序的。如果是顺序的,那么执行的数据库操作就是串行的。 我上面所有的内容都是根据表面内容的分析,可能不对。我猜测,仅仅是猜测,有可能是下面两个原因之一: 1 mongoskin 在处理异步回调的时候,有特殊的机制? 在这个特殊的机制里面有问题? 2 mongoose 有多个连接?每次操作自动从连接池里面分配一个连接和数据库交互,而mongoskin默认只使用了一个,需要手工管理多个连接?
-
mongoskin 是异步的
-
mongoskin只有一个连接, 如果你想要多个连接,
var db = mongoskin.db(‘localhost/test?poolSize=4’);
请看此行说明 https://github.com/kissjs/node-mongoskin/blob/master/lib/mongoskin/index.js#L42