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

 一切皆空2502861573 发布于 2022-11-09 20:47

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

我现在要做的就是拿到每一个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的执行结果中做操作了。

3 个回答
  • 可以试试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)
    
    2022-11-12 01:48 回答
  • 能否考虑使用闭包实现记录insert的状态,然后每次insert前判断。

    供参考。

    2022-11-12 01:48 回答
  • 把Tag抽出来 ,单独成一个Schema,通过ref 将两个Schema关联起来,获取信息的时候使用populate将关联的表的内容提取出来

    2022-11-12 01:48 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有