【发布时间】:2018-08-24 04:17:39
【问题描述】:
我有一个 Node.js 应用程序,它执行网页抓取并将一些信息保存在 json 对象中。 我也将此对象保存到文件中。
现在我想将这些信息保存到 MongoDB 数据库中。
这是我的代码结构:
app.js 文件:
var express = require('express');
// my files
var downloaderFirst = require('./routers/downloaderFirst.js');
var downloaderSecond = require('./routers/downloaderSecond.js');
// create app
const app = express();
downloaderFirst.download();
downloaderSecond.download();
./routers/downloaderFirst.js 文件:
var cheerio = require('cheerio');
var express = require('express');
var fs = require('fs');
var request = require('request');
var textract = require('textract');
// object of methods
var methods = {};
var url = 'http://www....';
// json object containing data
var jsons = [];
methods.download = function(req, res) {
extractText();
};
function extractText() {
// get text and save it to jsons array and ./output/dataFirst.json file
var thisYear = ...;
var thisObject = ...;
var o = {year: thisYear, object: thisObject};
jsons.push(o);
printOnFile(jsons, './output/dataFirst.json');
}
module.exports = methods;
./routers/downloaderSecondt.js 文件:
var cheerio = require('cheerio');
var express = require('express');
var fs = require('fs');
var request = require('request');
var textract = require('textract');
// object of methods
var methods = {};
var url = 'http://www....';
// json object containing data
var jsons = [];
methods.download = function(req, res) {
extractText();
};
function extractText() {
// get text and save it to jsons array and ./output/dataSecond.json file
var thisYear = ...;
var thisColor = ...;
var o = {year: thisYear, color: thisColor};
jsons.push(o);
printOnFile(jsons, './output/dataFirst.json');
}
module.exports = methods;
所以现在我有两个文件(dataFirst.json 和 dataSecond.json),其中包含如下对象:
dataFirst.json 文件:
[{
"year": "2006",
"object": "car"
},
{
"year": "2002",
"object": "car"
},
{
"year": "2006",
"object": "pen"
}, ...];
dataSecond.json 文件:
[{
"year": "2006",
"color": "red"
},
{
"year": "2002",
"color": "blue"
},
{
"year": "2006",
"color": "yellow"
}, ...];
我想使用称为first 和second 的两个不同集合将这些信息保存到MongoDB。
我想我可以做两件事:
- 从文件中获取这些文档并将它们全部保存
- 及时保存文档。因此,不要创建
dataFirst.json和dataSecond.json,而是将文档直接保存到数据库的正确集合中。
显然我使用 npm install mongodb --save 命令安装了 MongoDb 驱动程序。
无论如何,我想要一个函数来连接(如果不存在则创建)到 db,并插入文档。
所以我创建了 ./data/db.js 文件:
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/';
// object of methods
var methods = {};
methods.createDb = function(dbName) {
MongoClient.connect(url + dbName, function(err, db) {
if(err) {
throw err;
}
console.log('Database created!');
db.close();
});
}
methods.createCollection = function(dbName, collectionName) {
MongoClient.connect(url, function(err, db) {
if(err) {
throw err;
}
var dbo = db.db(dbName);
dbo.createCollection(collectionName, function(err, res) {
if(err) {
throw err;
}
console.log('Collection', collectionName, 'created!');
db.close();
});
});
}
methods.insertDoc = function(dbName, collectionName, doc) {
MongoClient.connect(url, function(err, db) {
if(err) {
throw err;
}
var dbo = db.db(dbName);
dbo.collection(collectionName).insertOne(doc, function(err, res) {
if(err) {
throw err;
}
console.log('1 document inserted');
db.close();
});
});
}
methods.insertManyDoc = function(dbName, collectionName, docs) {
MongoClient.connect(url, function(err, db) {
if(err) {
throw err;
}
var dbo = db.db(dbName);
dbo.collection(collectionName).insertMany(docs, function(err, res) {
if(err) {
throw err;
}
console.log('Number of documents inserted: ' + res.insertedCount);
db.close();
});
});
}
methods.insertFromFile = function(dbName, collectionName, filename) {
var objs = JSON.parse(fs.readFileSync(filename, 'utf8'));
this.insertManyDoc(dbName, collectionName, objs);
}
module.exports = methods;
对于解决方案 (1),我修改了我的 app.js 文件:
var express = require('express');
// my files
var downloaderFirst = require('./routers/downloaderFirst.js');
var downloaderSecond = require('./routers/downloaderSecond.js');
var db = require('./data/db.js');
var MongoClient = require('mongodb').MongoClient;
// create app
const app = express();
downloaderFirst.download();
downloaderSecond.download();
var dbName = 'db';
var firstCollectionName = 'first';
var secondCollectionName = 'second';
// create database
db.createDb(dbName);
// create the collections (tables in SQL)
db.createCollection(dbName, firstCollectionName);
db.createCollection(dbName, secondCollectionName);
db.insertFromFile(dbName, firstCollectionName, './output/dataFirst.json');
db.findAll(dbName, firstCollectionName);
问题是,如果我运行该项目两次,则该集合具有重复的文档,因为插入函数不会测试元素是否存在。
对于解决方案(2),我修改了 app.js 和 ./routers/downloaderFirst.js。
app.js 文件:
var express = require('express');
// my files
var downloaderFirst = require('./routers/downloaderFirst.js');
var downloaderSecond = require('./routers/downloaderSecond.js');
var db = require('./data/db.js');
var MongoClient = require('mongodb').MongoClient;
// create app
const app = express();
downloaderFirst.download();
downloaderSecond.download();
var dbName = 'db';
var firstCollectionName = 'first';
var secondCollectionName = 'second';
// create database
db.createDb(dbName);
// create the collections (tables in SQL)
db.createCollection(dbName, firstCollectionName);
db.createCollection(dbName, secondCollectionName);
./routers/downloaderFirst.js 文件:
var cheerio = require('cheerio');
var express = require('express');
var fs = require('fs');
var request = require('request');
var textract = require('textract');
var db = require('../data/db.js');
// object of methods
var methods = {};
var url = 'http://www....';
// json object containing data
var jsons = [];
methods.download = function(req, res) {
extractText();
};
function extractText() {
// get text and save it to jsons array and ./output/dataFirst.json file
var thisYear = ...;
var thisObject = ...;
var o = {year: thisYear, object: thisObject};
jsons.push(o);
printOnFile(jsons, './output/dataFirst.json');
db.insertDoc('db', 'first', obj);
}
module.exports = methods;
在这种情况下,我遇到了同样的问题(重复文件),然后我得到了这个错误:
数据库已创建!收藏首先创建!收藏第二 创建!插入的文档数:10692
C:...\node_modules\mongodb\lib\mongo_client.js:792 抛出错误; ^ MongoNetworkError: 首次连接时无法连接到服务器 [localhost:27017] [MongoNe tworkError: connect ECONNREFUSED 127.0.0.1:27017] 在游泳池。 (C:...\node_modules\mongodb-core\lib\topologies\server.js:503:11) 在 emitOne (events.js:116:13) 在 Pool.emit (events.js:211:7) 在连接处。 (C:...\node_modules\mongod b-core\lib\connection\pool.js:326:12) 在 Object.onceWrapper (events.js:317:30) 在 emitTwo (events.js:126:13) 在 Connection.emit (events.js:214:7) 在套接字。 (C:...\node_modules\mongodb-co re\lib\connection\connection.js:245:50) 在 Object.onceWrapper (events.js:315:30) 在 emitOne (events.js:116:13)
无论如何,如何修改我的代码以消除重复问题? 每次都连接和关闭连接好吗? 如何改进我的代码?我的意思是更好地组织代码。
我阅读了很多教程,但我无法解决我的问题。 对不起,如果这是一件愚蠢的事情,但这是我第一次使用Node.js,MongoDb,也是我第一次做网页抓取,所以现在我很困惑。
谢谢!
编辑 1
我是这样修改代码的:
app.js:
var express = require('express');
// my files
var downloaderFirst = require('./routers/downloaderFirst.js');
var downloaderSecond = require('./routers/downloaderSecond.js');
var db = require('./data/db.js');
var MongoClient = require('mongodb').MongoClient;
// create app
const app = express();
var dbName = 'db';
// create database
db.createDb(dbName);
downloaderFirst.download();
downloaderSecond.download();
db.disconnectDb(dbName);
./routers/downloaderFirst.js 文件:
var cheerio = require('cheerio');
var express = require('express');
var fs = require('fs');
var request = require('request');
var textract = require('textract');
var db = require('../data/db.js');
// object of methods
var methods = {};
var url = 'http://www....';
// json object containing data
var jsons = [];
methods.download = function(req, res) {
extractText();
};
function extractText() {
// get text and save it to jsons array and ./output/dataFirst.json file
var thisYear = ...;
var thisObject = ...;
var o = {year: thisYear, object: thisObject};
jsons.push(o);
printOnFile(jsons, './output/dataFirst.json');
db.insertDocFirst('db', 'first', obj);
}
module.exports = methods;
db.js 在哪里:
var fs = require('fs');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/';
// object of methods
var methods = {};
methods.createDb = function(dbName) {
MongoClient.connect(url + dbName, function(err, db) {
if(err) {
console.log('createDb', err);
//throw err;
}
console.log('Database created!');
var dbo = db.db(dbName);
var first = dbo.createCollection('first', function(err, res) {
if(err) {
console.log('create collection first', err);
//throw err;
}
console.log('Collection first created!');
/*// because we are searching by name, we need an index! without an index, things can get slow
first.ensureIndex({year: true, object: true}, function(err) {
if(err) {
throw err;
}
});
console.log('Index of collection first created!');*/
});
var second = dbo.createCollection('second', function(err, res) {
if(err) {
console.log('create collection second', err);
//throw err;
}
console.log('Collection second created!');
/*// because we are searching by name, we need an index! without an index, things can get slow
dbo.collection('second').createIndex({year: true, color: true}, function(err) {
if(err) {
console.log('ensureIndex second', err);
//throw err;
}
});
console.log('Index of collection second created!');*/
});
});
}
methods.disconnectDb = function(dbName) {
MongoClient.connect(url, function(err, db) {
if(err) {
console.log('disconnectDb', err)
//throw err;
}
console.log('Disconnected. Bye :)');
db.close();
});
}
methods.insertDocFirst = function(dbName, collectionName, doc) {
MongoClient.connect(url, function(err, db) {
if(err) {
console.log('insertDoc', err); // ** ERROR HERE **
//throw err;
}
var dbo = db.db(dbName);
var selector = {
"year": doc.year,
"color": doc.color
};
dbo.collection(collectionName).update(selector, doc, {upsert: true});
});
}
methods.insertDocSecond = function(dbName, collectionName, doc) {
MongoClient.connect(url, function(err, db) {
if(err) {
console.log('insertDoc', err);
//throw err;
}
var dbo = db.db(dbName);
var selector = {
"year": doc.year,
"object": doc.color
};
dbo.collection(collectionName).update(selector, doc, {upsert: true});
});
}
当我运行代码时,我得到:
Disconnected. Bye :)
Database created!
insertDoc { MongoNetworkError: failed to connect to server [localhost:27017] on first conn
ect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]
at Pool.<anonymous> (C:\...\node_modules\mongodb-core
\lib\topologies\server.js:503:11)
at emitOne (events.js:116:13)
at Pool.emit (events.js:211:7)
at Connection.<anonymous> (C:\...\node_modules\mongod
b-core\lib\connection\pool.js:326:12)
at Object.onceWrapper (events.js:317:30)
at emitTwo (events.js:126:13)
at Connection.emit (events.js:214:7)
at Socket.<anonymous> (C:\...\node_modules\mongodb-co
re\lib\connection\connection.js:245:50)
at Object.onceWrapper (events.js:315:30)
at emitOne (events.js:116:13)
name: 'MongoNetworkError',
message: 'failed to connect to server [localhost:27017] on first connect [MongoNetworkEr
ror: connect ECONNREFUSED 127.0.0.1:27017]' }
C:\...\node_modules\mongodb\lib\mongo_client.js:792
throw err;
^
TypeError: Cannot read property 'db' of null
at C:\...\data\db.js:105:16
at err (C:\...\node_modules\mongodb\lib\utils.js:414:
14)
at executeCallback (C:\...\node_modules\mongodb\lib\u
tils.js:403:25)
at C:\Users\...\node_modules\mongodb\lib\mongo_client.js:27
0:21
at connectCallback (C:\...\node_modules\mongodb\lib\m
ongo_client.js:940:5)
at C:\...\node_modules\mongodb\lib\mongo_client.js:78
9:11
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
显然我之前是这样启动MongoDb的:
mongod -dbpath C:\...\data
有什么问题?
编辑 2
非常感谢您的帮助。 我正在尝试修改添加集合的创建。
现在这是我的代码。
app.js:
var express = require('express');
// my files
var downloaderFirst = require('./routers/downloaderFirst.js');
var downloaderSecond = require('./routers/downloaderSecond.js');
var db = require('./data/db.js');
// create app
const app = express();
downloaderFirst.download();
downloaderSecond.download();
db.js:
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/';
let dbInstance;
// object of methods
var methods = {};
const connectDb = function(dbName, cb) {
if(dbInstance) {
return cb(dbInstance);
}
else {
MongoClient.connect(url + dbName, function(err, db) {
if(!err) {
dbInstance = db;
return cb(db);
}
});
}
}
methods.insertFirst = function(dbName, collectionName, doc) {
connectDb(dbName, function(db) {
var dbo = db.db(dbName);
var selector = {
year: doc.year,
color: doc.color
};
dbo.collection(collectionName).update(selector, doc, {upsert: true});
});
}
methods.insertSecond = function(dbName, collectionName, doc) {
connectDb(dbName, function(db) {
var dbo = db.db(dbName);
var selector = {
year: doc.year,
object: doc.object
};
dbo.collection(collectionName).update(selector, doc, {upsert: true});
});
}
./routers/downloaderFirst.js:
var cheerio = require('cheerio');
var express = require('express');
var fs = require('fs');
var request = require('request');
var textract = require('textract');
var db = require('../data/db.js');
// object of methods
var methods = {};
var url = 'http://www....';
// json object containing data
var jsons = [];
methods.download = function(req, res) {
extractText();
};
function extractText() {
// get text and save it to jsons array and ./output/dataFirst.json file
var thisYear = ...;
var thisObject = ...;
var o = {year: thisYear, object: thisObject};
jsons.push(o);
printOnFile(jsons, './output/dataFirst.json');
db.insertFirst('db', 'first', obj);
}
module.exports = methods;
当我跑步时,我得到:
(node:5708) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1
): MongoError: BSON field 'update.updates.q' is the wrong type 'array', expected type 'obj
ect'
(node:5708) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In
the future, promise rejections that are not handled will terminate the Node.js process wit
h a non-zero exit code.
(node:5708) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2
): MongoError: BSON field 'update.updates.q' is the wrong type 'array', expected type 'obj
ect'
(node:5708) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3
): MongoError: BSON field 'update.updates.q' is the wrong type 'array', expected type 'obj
ect'
^C
然后我可以使用 Compass 来分析我的数据库。 我看到集合已创建,但并非所有文档都应该存在。 “第二”集合中应该有 10692 个文档,“第一”集合中有 16102 个文档,但“第二”集合中有 2398 个文档,“第一”集合中有 933 个文档。
然后,我想到了如何(以及何时)调用 db.close()。 问题是我的应用程序应该进行网络抓取,将信息保存在 db 上,并使用 d3.js 可视化数据。 现在我想在应用程序完成时放置 db.close() 以将所有信息保存在 db 上。
如果节点是同步的,我会做这样的事情:
app.js:
var express = require('express');
// my files
var downloaderFirst = require('./routers/downloaderFirst.js');
var downloaderSecond = require('./routers/downloaderSecond.js');
var db = require('./data/db.js');
// create app
const app = express();
// web scraping and saving on db
downloaderFirst.download();
downloaderSecond.download();
// close connection
db.disconnectDb();
disconnectDb() 在 db.js 中的位置:
methods.disconnectDb = function(dbName) {
connectDb(dbName, function(db) {
var dbo = db.db(dbName);
db.close();
});
}
但这行不通。 那么,有什么窍门吗?这是我第一次使用 Node 和 Mongo,我阅读了很多资料,但我找不到完整(而且不是很简单)的示例来展示如何构建不同于“Hello World!”的应用程序。
谢谢
【问题讨论】:
-
为什么每次操作都要连接和断开??连接一次并执行操作,直到应用程序正常工作。当您的应用程序被
OS或you强制停止时,只需关闭连接即可。我认为这将解决问题
标签: javascript json node.js mongodb