Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 82 additions & 59 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,87 @@
'use strict';

const mongodb = require('mongodb');
const client = mongodb.MongoClient;
const {promisify} = require('util');

module.exports = bot;
const {MongoClient} = require('mongodb');

require('promise.prototype.finally').shim();


function ignoreNamespaceNotFound(error)
{
if(error.codeName !== 'NamespaceNotFound') return Promise.reject(error)
}


/**
* Helper function to import your data into a MongoDB database
*
* @param {object} config
* {
* fields: [], // {array} data to import
* database: 'name', // {string} name of database
* collection: 'collection' // {string|function} name of collection, or return a name
* host: 'localhost:27017', // {string} [optional] by default is 27017
* username: 'sofish', // {string} [optional]
* password: '***' // {string} [optional]
* }
*/
function bot({collection, database, drop, fields, host = '127.0.0.1:27027',
password, username})
{
if(!fields) {
return;
}

// remove empty fields;
fields = fields.filter(item => !!item);
if(!fields.length) return; // fields can be empty

// map collection
const collections = {};
if(typeof collection === 'function') {
fields.forEach(function(item)
{
const name = collection(item);

let col = collections[name]
if(!col) collections[name] = col = [];
col.push(item);
})
} else if(typeof collection === 'string') {
collections[collection] = fields;
} else {
throw new Error('`collection` is not specified');
}

function bot(config) {
/* Bot that helps to import your data into db
* @param {object} config
* {
* fields: [], // {array} data to import
* db: 'name', // {string} name of db
* collection: 'collection' // {string|function} name of collection, or return a name
* host: 'localhost:27017', // {string} [optional] by default is 27017
* username: 'sofish', // {string} [optional]
* password: '***' // {string} [optional]
* callback: (err, db) => {} // {function} [optional]
* }
*/

if(!config.host) config.host = '127.0.0.1:27027';
if(!config.callback) config.callback = () => {};

var callback = config.callback;
var auth = config.username ? `${config.username}:${config.password}@` : '';
client.connect(`mongodb://${auth}${config.host}/${config.db}`, (err, db) => {
if(err) return callback(err);

if(!config.fields || !config.fields.length) {
callback(null);
return db.close();
}

// remove empty fields;
let fields = config.fields.filter(item => !!item);
if(!fields.length) return db.close(); // fields can be empty

var c = config.collection;
var collections = {};

// map collection
if(typeof c === 'function') {
fields.forEach(item => {
var name = c(item);
if(collections[name]) return collections[name].push(item);
collections[name] = [item];
})
} else if(typeof c === 'string') {
collections[c] = fields;
} else {
callback({messsage: 'not matched, no `collection` is specific'});
}

var i = 0, l = Object.keys(collections).length - 1;
for(let c in collections) {
db.collection(c).insertMany(collections[c], (err, ret) => {
if(i++ === l) db.close();
if(err) return callback(err);
callback(null, ret);
});
}
const auth = username ? `${username}:${password}@` : '';

return MongoClient.connect(`mongodb://${auth}${host}/${database}`)
.then(function(client)
{
const promises = Object.keys(collections).map(function(key)
{
const collection = this.collection(key);

const promisedDrop = promisify(collection.drop .bind(collection))
const promisedInsertMany = promisify(collection.insertMany.bind(collection))

function insertMany()
{
return promisedInsertMany(collections[key]);
}

if(!drop) return insertMany();

return promisedDrop()
.catch(ignoreNamespaceNotFound)
.then(insertMany)
},
client.db(database));

return Promise.all(promises).finally(client.close.bind(client));
});
};
};


module.exports = bot;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"homepage": "https://github.com/sofish/mongoimport",
"dependencies": {
"mongodb": "^2.0.48"
"mongodb": "^3.0.6",
"promise.prototype.finally": "^3.1.0"
}
}
34 changes: 16 additions & 18 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
'use strict';

const mongoimport = require('../');
var host = '127.0.0.1:27017';
var db = 'mongoimport';
var collection = function(field) {
const mongoimport = require('..');

const host = '127.0.0.1:27017';
const database = 'mongoimport';
const collection = function(field) {
return field.name;
};
var fields = [
const fields = [
{ name: 'sofish', createdAt: '1986', isBot: 'guess me', isFun: 'try me' },
{ name: 'perf', foo: 'bar' },
{ name: 'error', hello: 'world' }
];
var config = {host, db, collection, callback, fields}

mongoimport(config, callback);

function callback(err, ret) {
if(err) {
if(err.message.match('ECONNREFUSED')) console.log('✘ make sure you have started mongodb server');
if(err.message.match('Authentication')) console.log('✘ make sure the username/password pair is matched');
console.log('= done!\n');
throw err.message;
}

console.log('✔ %d records inserted', ret.insertedCount);
mongoimport({host, database, collection, fields})
.then(function(ret) {
ret.forEach(ret => console.log('✔ %d records inserted', ret.insertedCount));
console.log('= done!\n');
},
function(err) {
if(err.message.match('ECONNREFUSED')) console.log('✘ make sure you have started mongodb server');
if(err.message.match('Authentication')) console.log('✘ make sure the username/password pair is matched');
console.log('= done!\n');
}
throw err.message;
});