for循环与mongoose操作数据库异步的问题

我现在需要对爬虫爬到的数据进行分析。
mongodb数据库中每个文档存储的是一个公司的信息(包括公司简介content,公司分类标签tag),一个公司可能有多个tag以逗号分隔

clipboard.png

我现在要做的就是拿到每一个tag的所有公司的简介,下面是每个tag文档的数据结构,一个tag对应多个公司的简介信息content,用array存储。

//des.js
var mongoose = require('./db.js'),
    Schema = mongoose.Schema;
var InfoSchema = new Schema({          
    tag: {type: String},
    content: {type: Array},
    total: {type: Number},
    salary: {type: Number},     
});
var Data = mongoose.model('desdata', InfoSchema, 'desdata');

function insert(obj){
    var data = new Data(obj);
    data.save(function(err, res){
        if(err) console.log('Error:' + err);
        else console.log('InesrtRes:' + res);
    })
}
function update(conditions, updateStr){
    var tmp;
    console.log('Update:', updateStr);
    if(updateStr.content) tmp = {$push, updateStr};
    else if(updateStr.total || updateStr.salary) tmp = {$inc, updateStr};
    console.log('Update: ', tmp);
    Data.update(conditions, tmp, function(err, res){
        if(err) console.log('Error:' + err);
        // else console.log(typeof res);
    })
}
function find(conditions){
    return Data.find(conditions).exec();
}

module.exports = {
    insert: insert,
    update: update,
    find: find
}

这是操作数据库代码:

var lagouInfo = require('./schema.js');
var desData = require('./des.js');

lagouInfo.find({'cid': {$gte:22777, $lte:22780}}, function(res){
    //这儿res拿到的是四篇文档,for循环瞬间执行完
    res.forEach(function(item, index){
        if(item.content.trim()){
            var tags = item.tag.trim().split(',');
            for(var i = 0; i < tags.length; i++){
                console.log('Tag:', tags[i]);
                desData.find({'tag': tags[i]}).then(function(res){
                    if(res.length == 0){
                        //我是需要根据insert之后数据库中的结果进行update的
                        desData.insert({
                            tag: tags[i],
                            content: [item.content],
                            total: 0,
                            salary: 0
                        })
                    }else{
                        desData.update({'tag': tags[i]}, {'content': item.content});
                    }
                }).catch(function(err){
                    console.log('Err:' + err);
                })
            }
        }
    })
})

感觉把所有数据库操作方法都写成promise的形式也不太合理,for循环这里还会有问题。

举个例子:

这是爬到的数据:

公司A:互联网、游戏
公司B:互联网

for循环希望的结果(最后得到两个文档):

互联网:公司A、公司B
游戏:公司A

实际的结果(最后是三个文档,因为先遍历的公司A,insert方法还没执行完,就遍历到公司B,这时数据库中没有tag互联网,所以还会insert):

互联网:公司A
互联网:公司B
游戏:公司A

不知道自己有没有把问题表述清楚,简洁点说就是希望每层for循环里的insert方法能和for每层执行是同步的,这样下层for执行时就可以从上一层for的执行结果中做操作了。

阅读 4.1k
3 个回答

把Tag抽出来 ,单独成一个Schema,通过ref 将两个Schema关联起来,获取信息的时候使用populate将关联的表的内容提取出来

能否考虑使用闭包实现记录insert的状态,然后每次insert前判断。

供参考。

新手上路,请多包涵

可以试试IIFE

function(i){
    desData.find({'tag': tags[i]}).then(function(res){
                    if(res.length == 0){
                        //我是需要根据insert之后数据库中的结果进行update的
                        desData.insert({
                            tag: tags[i],
                            content: [item.content],
                            total: 0,
                            salary: 0
                        })
                    }else{
                        desData.update({'tag': tags[i]}, {'content': item.content});
                    }
                }).catch(function(err){
                    console.log('Err:' + err);
                })
}(i)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题