javascript - 尽管之前有相同的连接工作,但 mongodb 'failed to connect to server' 错误

标签 javascript node.js mongodb node-mongodb-native

更新: 使用手动提供的参数单独运行 getSections 函数似乎工作正常。打印出导致错误的参数后,每次都是不同的设置...


我有一个 updateCurrentTerm() 函数,它调用其中的几个不同函数,所有这些函数都会更新同一数据库的不同集合。其中每一个都以完全相同的方式连接到数据库,如下所示:

MongoClient.connect(MONGOURL + term, (err, db) => {

其中MONGOURL'mongodb://localhost:27017/'term'4650' 。但是,该连接似乎适用于 getSchoolsgetSubjectsgetCourses,但不适用于 getSections。这是我收到的完整错误:

TypeError: Cannot read property 'collection' of null
    at /Users/Joon/sans/app.js:129:26
    at connectCallback (/Users/Joon/sans/node_modules/mongodb/lib/mongo_client.js:315:5)
    at /Users/Joon/sans/node_modules/mongodb/lib/mongo_client.js:222:11
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)

我进一步调查:MongoClient.connect回调的db参数为null意味着err参数不为null。 err 参数包含以下内容:

{ MongoError: failed to connect to server [localhost:27017] on first connect
    at .<anonymous> (/Users/Joon/sans/node_modules/mongodb-core/lib/topologies/server.js:313:35)
    at emitOne (events.js:96:13)
    at emit (events.js:188:7)
    at .<anonymous> (/Users/Joon/sans/node_modules/mongodb-core/lib/connection/pool.js:271:12)
    at g (events.js:286:16)
    at emitTwo (events.js:106:13)
    at emit (events.js:191:7)
    at Socket.<anonymous> (/Users/Joon/sans/node_modules/mongodb-core/lib/connection/connection.js:165:49)
    at Socket.g (events.js:286:16)
    at emitOne (events.js:96:13)
  name: 'MongoError',
  message: 'failed to connect to server [localhost:27017] on first connect' }

任何帮助将不胜感激。谢谢!


app.js

import { MongoClient } from 'mongodb';
import request from 'request-json';
import { EventEmitter } from 'events';

const API = request.createClient('http://www.northwestern.edu/class-descriptions/');
const MONGOURL = 'mongodb://localhost:27017/';
const EVENT = new EventEmitter();


const makeRequest = (query, type, callback) => {
    // Possible types:
    // terms
    // schools
    // subjects
    // courses
    // sections
    // details

    // Prepare query with correct ending
    if (type === 'terms') {
        query = 'index-v2.json';
    } else if (type === 'details') {
        query += '-v2.json';
    } else {
        query += '/index-v2.json';
    }

    API.get(query, (err, response, body) => {
        if (err) {
            console.log(err);

            callback(null, err);
        } else {
            // Parse out last non-data term
            const last = body[body.length - 1];
            const lastKeys = Object.keys(last);
            if (lastKeys.length === 1 && lastKeys[0] === 'ignore') {
                body.pop();
            }

            callback(body, null);
        }
    });
}

const getTerms = (callback) => {
    // TODO: Refactor to insert only if new term
    MongoClient.connect(MONGOURL + 'terms', (err, db) => {
        const coll = db.collection('data');
        coll.remove(); // Start clean
        makeRequest('', 'terms', (data, err) => {
            if (!err) {
                coll.insertMany(data, (err, result) => {
                    db.close();
                    callback(data);
                });
            } else {
                db.close();
            }
        });
    });
};

const getSchools = (term, callback) => {
    // term is the term id (not the mongodb _id)
    MongoClient.connect(MONGOURL + term, (err, db) => {
        const schools = db.collection('schools');
        makeRequest(term, 'schools', (data, err) => {
            if (!err) {
                schools.insertMany(data, (err, result) => {
                    db.close();
                    callback(data);
                });
            } else {
                db.close();
            }
        });
    });
};

const getSubjects = (term, school, callback) => {
    // term is the term id (not the mongodb _id)
    // school is the school id (not the mongodb _id)
    MongoClient.connect(MONGOURL + term, (err, db) => {
        const subjects = db.collection('subjects');

        const query = term + '/' + school;
        makeRequest(query, 'subjects', (data, err) => {
            if (!err) {
                subjects.insertMany(data, (err, result) => {
                    db.close();
                    callback(data);
                });
            } else {
                db.close();
            }
        });
    });
};

const getCourses = (term, school, subject, callback) => {
    // term is the term id (not the mongodb _id)
    // school is the school id (not the mongodb _id)
    // subject is the subject abbv
    MongoClient.connect(MONGOURL + term, (err, db) => {
        const courses = db.collection('courses');

        const query = term + '/' + school + '/' + subject;
        makeRequest(query, 'courses', (data, err) => {
            if (!err) {
                courses.insertMany(data, (err, result) => {
                    db.close();
                    callback(data);
                });
            } else {
                db.close();
            }
        });
    });
};

const getSections = (term, school, subject, course, callback) => {
    // term is the term id (not the mongodb _id)
    // school is the school id (not the mongodb _id)
    // subject is the subject abbv
    // course is the course abbv
    MongoClient.connect(MONGOURL + term, (err, db) => {
        console.log(err);
        const sections = db.collection('sections');

        const query = term + '/' + school + '/' + subject + '/' + course;
        makeRequest(query, 'sections', (data, err) => {
            if (!err) {
                sections.insertMany(data, (err, result) => {
                    db.close();
                    callback(data);
                });
            } else {
                db.close();
            }
        });
    });
};

const getDetails = (term, school, subject, course, section, callback) => {
    // term is the term id (not the mongodb _id)
    // school is the school id (not the mongodb _id)
    // subject is the subject abbv
    // course is the course abbv
    // section is the section id (not the mongodb _id)
    MongoClient.connect(MONGOURL + term, (err, db) => {
        const details = db.collection('details');

        const query = term + '/' + school + '/' + subject + '/' + course + '/' + section;
        makeRequest(query, 'details', (data, err) => {
            if (!err) {
                details.insertMany(data, (err, result) => {
                    callback(data);
                });
            } else {
                db.close();
            }
        });
    });
};

const updateCurrentTerm = () => {
    MongoClient.connect(MONGOURL + 'terms', (err, db) => {
        const terms = db.collection('data');
        // Find term with max id (not mongodb _id)
        terms.find().sort({id:-1}).limit(1).next((err, doc) => {
            EVENT.emit('maxTerm', doc.id);
            db.close();
        });
    });

    EVENT.on('maxTerm', (term) => {
        MongoClient.connect(MONGOURL + term, (err, db) => {
            db.collection('schools').remove();
            db.collection('subjects').remove();
            db.collection('courses').remove();
            db.collection('sections').remove();
            db.collection('details').remove();
            db.close();
            EVENT.emit('clean', term);
        });
    });

    EVENT.on('clean', (term) => {
        getSchools(term, (data) => {
            EVENT.emit('updatedSchools', term, data);
        });
    });

    EVENT.on('updatedSchools', (term, data) => {
        data.forEach((school) => {
            getSubjects(term, school.id, (newData) => {
                EVENT.emit('updatedSubjects', term, school.id, newData);
            });
        });
    });

    EVENT.on('updatedSubjects', (term, school, data) => {
        data.forEach((subject) => {
            getCourses(term, school, subject.abbv, (newData) => {
                EVENT.emit('updatedCourses', term, school, subject.abbv, newData);
            });
        });
    });

    EVENT.on('updatedCourses', (term, school, subject, data) => {
        data.forEach((course) => {
            getSections(term, school, subject, course.abbv, (newData) => {
                EVENT.emit('updatedSections', term, school, subject, course.abbv, newData);
            });
        });
    });
}

updateCurrentTerm();

最佳答案

每次运行查询时,都会创建一个新实例,并且与 mongod 的连接太多!这是行不通的,因为每个实例将创建并保留至少一个连接(但默认情况下为 10 个),并且只有当 Java GC 清理您的 Mongo 实例或调用 close() 时,这些连接才会被删除。

创建与 Mongo 的新连接成本非常高,而且还会降低 mongod 的性能。因此,创建一个 Mongo 实例并使其尽可能长时间地保持事件状态!使用返回延迟创建实例的静态方法 getInstance() 实现 MongoFactory 就可以很好地完成任务。

关于javascript - 尽管之前有相同的连接工作,但 mongodb 'failed to connect to server' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40781075/

相关文章:

javascript - 如何在集合中过滤mongoDB中的查询

javascript - 不稳定的 jQuery UI 拖动时可排序

php - 如何在将变量加载到 cake php 的页面之前将变量附加到所有 javascript 文件?

html - 如何使用带有标准 HTML 而不是 Jade 的 Piler?

mongodb - 无法识别的字段: 'ntoreturn' error in documenDB

javascript - Javascript 中的 Excel 到 JSON 模式

javascript - jQuery 随机化图片

javascript - 脚本警报错误: Object expected

javascript - 在Javascript中绑定(bind)回调函数? (不要与 Function.prototype.bind() 混淆)

mongodb - 高级数据聚合 : counting average in MongoDB collections