我现在需要对爬虫爬到的数据进行分析。
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的执行结果中做操作了。
可以试试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)
能否考虑使用闭包实现记录insert的状态,然后每次insert前判断。
供参考。
把Tag抽出来 ,单独成一个Schema,通过ref 将两个Schema关联起来,获取信息的时候使用populate将关联的表的内容提取出来