更新: 使用手动提供的参数单独运行 getSections 函数似乎工作正常。打印出导致错误的参数后,每次都是不同的设置...
我有一个 updateCurrentTerm() 函数,它调用其中的几个不同函数,所有这些函数都会更新同一数据库的不同集合。其中每一个都以完全相同的方式连接到数据库,如下所示:
MongoClient.connect(MONGOURL + term, (err, db) => {
其中MONGOURL
是'mongodb://localhost:27017/'
,term
是'4650'
。但是,该连接似乎适用于 getSchools
、getSubjects
、getCourses
,但不适用于 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/