I'm new to mongo and node and i'm trying to create a script that essentially works similar to rails rake db:seed
task where I have a set of .json files in a specific folder, and when I run $ node seed
it will run my seed.js file which takes all of those .json files and inserts the contents into their appropriate mongo collections based on the filename of the .json file.
Essentially I run $ node seed
and it executes /seed.js
which looks at /seeds/account.json
, /seeds/customer.json
, etc.
This way I can mit this code and then next developer can just run $ node seed
and his mongo instance will be populated with some data to work with.
The problem i'm having is that the data that I got is from a dump of my collections in mongo so some sample data for account looks like this:
{ _id: { '$oid': '534d832177da4e0d38000001' },
id: 1,
name: something,
dateTime: '2014-04-15T14:06:09-05:00' }
Now when I run $ node seed
, I get this error:
[Error: key $oid must not start with '$']
Is there any way to get around this error or am I going to have to remove all the $oid
's from all my .json files?
seed.js:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/testdb');
var dir = './seeds';
var db = mongoose.connection;
// Show connection error if there is one
db.on('error', console.error.bind(console, 'Database Connection Error:'));
// If we successfully connected to mongo
db.once('open', function callback() {
var fs = require('fs'); // Used to get all the files in a directory
// Read all the files in the folder
fs.readdir(dir, function(err, list) {
// Log the error if something went wrong
if(err) {
console.log('Error: '+err);
}
// For every file in the list
list.forEach(function(file) {
// Set the filename without the extension to the variable collection_name
var collection_name = file.split(".")[0];
var parsedJSON = require(dir + '/' + file);
for(var i = 0; i < parsedJSON.length; i++) {
// Counts the number of records in the collection
db.collection('cohort').count(function(err, count) {
if(err) {
console.log(err);
}
});
db.collection(collection_name).insert(parsedJSON[i], function(err, records) {
if(err) {
console.log(err);
}
console.log(records[0]);
console.log("Record added as "+records[0]);
});
}
});
});
});
Or is there any libraries out there that already exist for this kind of task?
I'm new to mongo and node and i'm trying to create a script that essentially works similar to rails rake db:seed
task where I have a set of .json files in a specific folder, and when I run $ node seed
it will run my seed.js file which takes all of those .json files and inserts the contents into their appropriate mongo collections based on the filename of the .json file.
Essentially I run $ node seed
and it executes /seed.js
which looks at /seeds/account.json
, /seeds/customer.json
, etc.
This way I can mit this code and then next developer can just run $ node seed
and his mongo instance will be populated with some data to work with.
The problem i'm having is that the data that I got is from a dump of my collections in mongo so some sample data for account looks like this:
{ _id: { '$oid': '534d832177da4e0d38000001' },
id: 1,
name: something,
dateTime: '2014-04-15T14:06:09-05:00' }
Now when I run $ node seed
, I get this error:
[Error: key $oid must not start with '$']
Is there any way to get around this error or am I going to have to remove all the $oid
's from all my .json files?
seed.js:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/testdb');
var dir = './seeds';
var db = mongoose.connection;
// Show connection error if there is one
db.on('error', console.error.bind(console, 'Database Connection Error:'));
// If we successfully connected to mongo
db.once('open', function callback() {
var fs = require('fs'); // Used to get all the files in a directory
// Read all the files in the folder
fs.readdir(dir, function(err, list) {
// Log the error if something went wrong
if(err) {
console.log('Error: '+err);
}
// For every file in the list
list.forEach(function(file) {
// Set the filename without the extension to the variable collection_name
var collection_name = file.split(".")[0];
var parsedJSON = require(dir + '/' + file);
for(var i = 0; i < parsedJSON.length; i++) {
// Counts the number of records in the collection
db.collection('cohort').count(function(err, count) {
if(err) {
console.log(err);
}
});
db.collection(collection_name).insert(parsedJSON[i], function(err, records) {
if(err) {
console.log(err);
}
console.log(records[0]);
console.log("Record added as "+records[0]);
});
}
});
});
});
Or is there any libraries out there that already exist for this kind of task?
Share Improve this question edited Jun 26, 2017 at 12:56 Neil Lunn 151k36 gold badges355 silver badges325 bronze badges asked Apr 21, 2014 at 21:10 CatfishCatfish 19.3k60 gold badges213 silver badges358 bronze badges4 Answers
Reset to default 3So there is a thing called the extended JSON syntax which is more of a spec and while supported by some driver implementations is yet to be implemented in the node native driver itself.
While there is one implementation I know of to work with converting these types, in the jsontomongo module for node, all of the types are not strictly supported. Yet as can clearly be seen in the code:
'use strict';
module.exports = function (query) {
var key, val;
for (key in query) {
if (!query.hasOwnProperty(key)) continue;
val = query[key];
switch (key) {
case '$date':
return new Date(val);
case '$regex':
return new RegExp(val, query.$options);
case '$undefined':
return undefined;
}
if (typeof val === 'object')
query[key] = module.exports(val);
}
return query;
};
Implementing the full specification or just the things you need such as ObjectId
would be a fairly trivial exercise. You might even want to contribute your work as a node module yourself.
So that is essentially the sort of code you need to parse the object structure that results from parsing the JSON string.
Use this instead of $oid:
{ "_id" : ObjectId("5063114bd386d8fadbd6b004")}
Use mongodb-extended-json
npm extension: https://www.npmjs./package/mongodb-extended-json
Here is the usage example taken from documentation:
var EJSON = require('mongodb-extended-json');
var BSON = require('bson');
var doc = {
_id: BSON.ObjectID(),
last_seen_at: new Date(),
display_name: undefined
};
console.log('Doc', doc);
// > Doc { _id: 53c2ab5e4291b17b666d742a, last_seen_at: Sun Jul 13 2014 11:53:02 GMT-0400 (EDT), display_name: undefined }
console.log('JSON', JSON.stringify(doc));
// > JSON {"_id":"53c2ab5e4291b17b666d742a","last_seen_at":"2014-07-13T15:53:02.008Z"}
console.log('EJSON', EJSON.stringify(doc));
// > EJSON {"_id":{"$oid":"53c2ab5e4291b17b666d742a"},"last_seen_at":{"$date":1405266782008},"display_name":{"$undefined":true}}
// And likewise, EJSON.parse works just as you would expect.
EJSON.parse('{"_id":{"$oid":"53c2ab5e4291b17b666d742a"},"last_seen_at":{"$date":1405266782008},"display_name":{"$undefined":true}}');
// { _id: 53c2ab5e4291b17b666d742a,
// last_seen_at: Sun Jul 13 2014 11:53:02 GMT-0400 (EDT),
http://docs.mongodb/manual/core/document/#field-names
The field names cannot start with the dollar sign ($) character.
Part of the mongodb spec as it uses $ to indicate operations like $inc or $unset.