-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathimport.js
More file actions
146 lines (124 loc) · 4.59 KB
/
import.js
File metadata and controls
146 lines (124 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env node
const _ = require('lodash');
const async = require('async');
const fsBackend = require('./backends/fs');
const mongoBackend = require('./backends/mongo');
const resolveSelections = require('./utils/resolveSelections');
const typecast = require('./utils/typecast');
const parsePotentialArray = require('./utils/parsePotentialArray');
const LIMIT = 1;
/**
* Actual logic to import multiple collections
* from defined directory (reads all JSON files)
*
* @param {opts.collections} array list of collections to import
* @param {opts.connection} MongoDBClient an instance of MongoDB client connected to DB
* @param {opts.dataDir} string source directory with the data
* @param {callback} function A standard callback with function(err) signature
*/
function importCollections(opts, callback) {
const list = opts.collections;
const dbConn = opts.connection;
const dataDir = opts.dataDir;
if (!Array.isArray(list) || !list.length) {
return callback('No collections provided to importCollections method.');
}
if (!dbConn) {
return callback('MongoDBClient must be provided to importCollections method.');
}
if (!dataDir) {
return callback('dataDir must be provided to importCollections method.');
}
function importOne(collection, cb) {
if (!collection) {
return cb('> Missing collection name in call to importOne method');
}
//console.log(collection);
collection = /[^/]*$/.exec(collection)[0];
return fsBackend.readFile(`${dataDir}/${collection}.json`, (readErr, readData) => {
//return fsBackend.readFile(`${collection}.json`, (readErr, readData) => {
if (readErr) {
return cb(readErr);
}
if (opts.verbose) {
console.log(`┌ Importing "${collection}" (${readData.length} documents)`);
}
const col = dbConn.collection(collection);
const dataToInsert = _.map(readData, typecast.unwrap);
if (!dataToInsert || Array.isArray(dataToInsert) && !dataToInsert.length) {
return cb();
}
return col.insertMany(dataToInsert, (writeErr) => {
if (writeErr) {
if (opts.verbose) {
console.log(`└ Error while importing "${collection}" collection.`);
console.error(`\x1b[31m ${writeErr.errmsg}\x1b[0m`);
}
// if (writeErr.code === 11000) {
// console.log('You can ignore index restoration with --noIndex');
// console.log('You can try dropping the database and trying again.');
// }
return cb(writeErr);
}
if (opts.verbose) {
console.log(`└ Successfully imported "${collection}" collection.`);
}
return cb(null, { collection, documents: readData.length });
});
});
}
// process each file and insert in Mongo
return async.mapLimit(list, LIMIT, importOne, (importErr, importResult) => {
if (importErr) {
return callback(importErr);
}
mongoBackend.close(dbConn);
return callback(null, importResult);
});
}
/**
* Main exportable function
*
* @param {opts.host} string Database host
* @param {opts.db} string Database name
* @param {opts.dataDir} string Local directory with data to import
* @param {opts.include} array (optional) list of collections to include
* defaults to all collections
* @param {opts.exclude} array (optional) list of collections to exclude
* (applied after include list; takes precedence)
* @param {callback} function A standard callback with function(err) signature
*/
function main(opts, callback) {
if (!opts || !opts.host || !opts.db) {
throw new Error('"host" and "db" must be provided');
}
if (typeof callback !== 'function') {
throw new Error('"callback" must be provided');
}
if (typeof opts.dataDir !== 'string') {
throw new Error('"dataDir" must be provided');
}
const dataDir = fsBackend.resolvePath(opts.dataDir);
const collectionsToInclude = parsePotentialArray(opts.include);
const collectionsToExclude = parsePotentialArray(opts.exclude);
// 1. get collections
const allCollections = fsBackend.scanDirSync(dataDir);
const resolved = resolveSelections(
allCollections,
collectionsToInclude,
collectionsToExclude
);
mongoBackend.open(opts.host, opts.db, (connErr, connDb) => {
if (connErr) {
console.error('Couldn\'t connect to specified MongoDB', connErr);
return process.exit(2);
}
const newOpts = {
collections: resolved.selected,
connection: connDb,
dataDir
};
return importCollections(newOpts, callback);
});
}
module.exports = main;