错误:服务器实例池在嵌套的数据库集合函数中被破坏

时间:2019-05-23 08:15:05

标签: node.js mongodb

我已搜索标题中指定的错误的解决方案。

  

MongoError:服务器实例池已损坏

我相信这是因为db.close()的位置错误。但是我嵌套dbo.collection,无法获得此错误的确切解决方案。

首先,我从数据库中获取数据(状态为ID的ID数组),然后将它们与URL逐一连接(每个app-id),以获得所需的appUrl,该appUrl将用于逐一爬网数据。然后将抓取的数据存储到另一个mongoDB集合中。将对数组中的每个ID重复此过程。但是我的代码在将数据存储到集合之前有“服务器实例池被破坏”的错误。我正在放错db.close()的位置,但无法解决。请帮助我解决此错误

  

这是我的代码

 ///* global sitehead */
const request = require('request');
const cheerio = require('cheerio');
//const response = require('response');
const fs = require('fs');
const express = require('express');
const app = express();
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
var dateTime = require('node-datetime');
MongoClient.connect(url, {useNewUrlParser: true}, function (err, db) {
    if (err) {
        throw err;
    } else {
        var dbo = db.db("WebCrawler");
        var app_id;
        var appUrl;
        let arr = [];
        dbo.collection("Unique_Apps").find({"Post_Status": 0}, {projection: {_id: 0, App_Id: 1}}).toArray(function (err, result)
        {
            // console.log(result);
            if (err) {
                throw err;
                // console.log(err);
            } else {
                for (var i = 0; i < result.length; i++)
                {
                    arr[i] = result[i];

                }
                arr.forEach((el) => {
                    app_id = el.App_Id;
                    //console.log(app_id);
                    appUrl = 'https://play.google.com/store/apps/details?id=' + app_id;
                    console.log(appUrl);
                    request(appUrl, function (error, response, html) {
                        if (!error && response.statusCode === 200) {

                            //START Crawling @@@@@@@@@@@
                            const $ = cheerio.load(html); //cheerio
                            const appTitle = $('.AHFaub');
                            const iconUrl = $('.T75of.sHb2Xb').attr("src");
                            const developedBy = $('.T32cc.UAO9ie').children().eq(0);
                            const category = $('.T32cc.UAO9ie').children().eq(1);

                            //store in database collection: "Single_App_Data_Post" 
                            var curr_obj = {App_Id: app_id, App_Name: appTitle.text(),
                                Icon_Url: iconUrl, Price: "Free", Developed_By: developedBy.text(),
                                Category: category.text()
                            };
                            dbo.collection("Single_App_Data_Post").insertOne(curr_obj, function (err, res) {
                                console.log("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
                                if (err) {
                                    throw err;
                                    // console.log(err);
                                } else {
                                    console.log("inserted....");
                                } //main else     
                            });
                            dbo.collection("Unique_Apps").updateOne({App_Id: app_id}, {$set: {Post_Status: 0}}, function (err, res) {
                                if (err)
                                    throw err;
                                console.log("1 document updated");
                                //dbo.close();
                            });
                        } else
                        {
                            throw error;
                        }

                    });
                });
            }
            db.close();
        });

    } //else 

}); //mongoClient connect db
  

输出

Output

1 个答案:

答案 0 :(得分:1)

以下是有关如何将回调转化为Promise的良好开端。尝试使用它,逐个执行代码块,理解它,然后将您的updateOne / insertOne请求添加到其中。

const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');
const express = require('express');
const app = express();

const MongoClient = require('mongodb').MongoClient;
const dateTime = require('node-datetime');

// Class used to handle the database basic interractions
class DB {
  constructor() {
    this.db = false;
    this.url = "mongodb://localhost:27017/";
  }

  // Do connect to the database
  connect() {
    return new Promise((resolve, reject) => {
      MongoClient.connect(this.url, {
        useNewUrlParser: true,
      }, (err, db) => {
        if (err) {
          console.log('error mongodb connect');

          return reject(err);
        }

        this.db = db;

        return resolve(db);
      });
    });
  }

  disconnect() {
    db.close();

    this.db = false;
  }

  getCollection(name) {
    return this.db.db(name);
  }
}

// Get the data from the database
function getAppsIds(dbObj) {
  return new Promise((resolve, reject) => {
    const dbo = dbObj.getCollection('WebCrawler');

    dbo.collection('Unique_Apps').find({
      'Post_Status': 0,
    }, {
      projection: {
        _id: 0,
        App_Id: 1,
      }
    }).toArray(function(err, result) {
      if (err) {
        return reject(err);
      }

      return resolve(result);
    });
  });
}

function requestPlayStore(idApp) {
  return new Promise((resolve, reject) => {
    const appUrl = `https://play.google.com/store/apps/details?id=${app_id}`;

    request(appUrl, function(error, response, html) {
      if (error || response.statusCode !== 200) {
        return reject(error);
      }

      return resolve({
        response,
        html,
      });
    });
  });
}

// Do treat one id app at a time
function treatOneIdApp(dbObj, idApp) {
  return requestPlayStore(idApp)
    .then(({
      response,
      html,
    }) => {
      // Perform your requests here updateOne and insertOne ...
    });
}

const dbObj = new DB();

dbObj.connect()
  .then(() => getAppsIds(dbObj))
  .then(rets => Promise.all(rets.map(x => treatOneIdApp(dbObj, x.App_Id))))
  .then(() => dbObj.disconnect())
  .catch((err) => {
    console.log(err);
  });