mongoskin在处理bind后的函数的时候,好像有问题。
发布于 3年前 作者 darklowly 2145 次浏览 最后一次编辑是 5个月前 来自 问答
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不是串行的。

9 回复

大侠,请问您如何得知console有dir这个方法的?

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默认只使用了一个,需要手工管理多个连接?

@darklowly

  1. mongoskin 是异步的

  2. mongoskin只有一个连接, 如果你想要多个连接,

    var db = mongoskin.db(‘localhost/test?poolSize=4’);

请看此行说明 https://github.com/kissjs/node-mongoskin/blob/master/lib/mongoskin/index.js#L42

@guilin 看到了,有时间了再测试一下。谢谢。

我是从chrome dev tools的官方文档上看的。

this.update 这个方法是mongoskin自带的吗 还是mongo原生的呢

回到顶部