Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jwatson3d/cd519ce76b0b55d72734a1cd932b940a to your computer and use it in GitHub Desktop.
Save jwatson3d/cd519ce76b0b55d72734a1cd932b940a to your computer and use it in GitHub Desktop.

Revisions

  1. @bclinkinbeard bclinkinbeard created this gist Mar 15, 2013.
    105 changes: 105 additions & 0 deletions referenced_mongo_json.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,105 @@
    #### Populating referenced collections in MongoDB from JSON files using Node.js and Mongoose

    I recently began working with Node and MongoDB for a small personal project, largely just to learn the technologies. One thing that is fairly simple but that I found far from obvious and lacking in concrete examples was how to populate the part of my database that used referenced collections from the sample JSON data I was starting with. This post attempts to fill that gap using the following code snippets, which are heavily commented inline. You will notice I am using the awesome [Mongoose](http://mongoosejs.com/) library which makes working with MongoDB very easy.

    ```javascript
    http.createServer( app ).listen( app.get( 'port' ), function() {

    mongoose.connect( 'mongodb://localhost/{YOUR_DB_NAME}' );

    var db = mongoose.connection;
    db.on( 'error', console.error.bind( console, 'connection error:' ) );

    // once the connection is established we define our schemas
    db.once( 'open', function callback() {

    // independent schema
    var FoodSchema = new Schema( {
    name: String,
    unit: String,
    p: Number,
    f: Number,
    c: Number
    } );

    // this schema represents a collection whose documents
    // will each hold a reference to a single document
    // from the FoodSchema collection
    var LogEntrySchema = new Schema( {
    date: Date,
    qty: Number,
    // starting the name with an underscore is simply a convention
    // to denote this field as a reference
    // the type instructs Mongoose to set this up as a reference
    // to another document's _id property, which is automatically
    // generated by MongoDB. the ref field refers to the Model name
    _food: { type: Schema.Types.ObjectId, ref: 'Food' }
    } );

    // create Mongoose models from our schemas
    var Food = mongoose.model( 'Food', FoodSchema );
    var LogEntry = mongoose.model( 'LogEntry', LogEntrySchema );

    } );

    } );
    ```

    During development I simply defined a route that I could load to trigger a database rebuild. This proved very useful as I would regularly muck things up while working on a new form or other piece of the app. Below is the code for (re)populating the database from JSON files.

    ```javascript
    var mongoose = require( 'mongoose' )
    , _ = require( 'lodash' )
    , foodData = require( './mockdata/foodData.json' )
    , logData = require( './mockdata/logData.json' );

    exports.reset = function( req, res ) {

    // get refs to the models we defined above
    var Food = mongoose.model( 'Food' );
    var LogEntry = mongoose.model( 'LogEntry' );

    // clear all existing documents from the collections
    Food.find().remove();
    LogEntry.find().remove();

    // populate the foods collection from json data
    // nothing fancy here as Food documents do not reference anything else
    for( var i = 0; i < foodData.length; i++ ) {
    new Food( foodData[ i ] ).save();
    }

    // now that the collection is populated we iterate over it
    Food.find( function( err, foods ) {
    var foodMap = {};

    // store _ids of Food documents that Mongo generated upon insert
    for( var i = 0; i < foods.length; i++ ) {
    var food = foods[i];
    // I am mapping the ids to the food names because the LogEntry
    // JSON data contained this field thanks to the original source
    // data's structure (a spreadsheet).
    // You could utilize a more sophisticated lookup here if necessary.
    foodMap[ food.name ] = food._id;
    }

    // populate the LogEntries collection from json data
    for( i = 0; i < logData.length; i++ ) {
    var logEntry = logData[ i ];
    // we find and store food._id on LogEntry for reference
    logEntry._food = foodMap[ logEntry.food_name ];

    // note that only the fields defined in the schema will be
    // persisted to Mongo, so the foodName field we used for
    // lookup will not be unnecessarily added to the db
    new LogEntry( logEntry ).save();
    }
    } );

    res.redirect( "/" );
    };
    ```

    And there you have it. Far from revolutionary, but hopefully it will help someone get up and running a bit more quickly than I did, though I have to say I was pleasantly surprised with how quickly I was able to be productive with these new (to me) technologies. If you have corrections or suggestions for improvement please leave a comment or fork this Gist.

    Enjoy!