How to seed dependent data in Node/MongoDB
Asked Answered
I

1

2

I am trying to seed a MongoDB database with a one-to-many relationship using objectID's. Something like the following:

var postSchema = mongoose.Schema({
  name: {type: String, required: true, unique: true},
  description: {type: String},
  userlikes: [{type: mongoose.Schema.Types.ObjectId, ref: 'Users'}]
});

A synchronous implementation of this would look something like this (pseudocode):

openConnection()
cleardb()
users = createUsers()  
post = createPost(users)

Using Node I need to nest each of these calls which gets messy and makes re-use of objects difficult (I may want to create further dependent objects after). I have had a look at async but that doesn't appear to help too much in this case - I could use async.waterfall but that would give me something similar to the nested solution only flattened into an array.

When seeding related data it obviously helps if you can create data objects and then assume they exist for building subsequent data structures. Obviously this doesn't really happen with an asynchronous approach. Am I missing the point here?

I would assume that with node used so extensively for API's this would be a common challenge for setting up data for testing but I can't find an elegant solution documented anywhere.

Can anyone point me to an example implementation of how this problem is solved in a node setup?

Insured answered 17/10, 2015 at 11:41 Comment(0)
D
1

using async could be very handy.
all business logic/task in the end of the day is just a sequence of operations. waterfall is an abstraction very useful to your solution.

for instance: seed.js

var User = require('../path/to/your/models/User');
var Post = require('../path/to/your/models/Post');
var DB   = require('../path/to/your/database/boot/module');
var config = require('../path/to/your/configuration');

function startDB(config, callback) {
  DB.start(config, callback);
}

function createUsers(userParams, callback) {
  User.save(userParams, callback); 
}

function createPost(users, callback) {
  Post.save(users, callback);
}

function resolvedCallback(err, posts) {
  if (err)
    return your-error-handling-here;

  console.log(posts);
  DB.cleanup(console.log.bind(null, 'clean up finished: '));
}

async.waterfall([
  async.constant({ db: config.dbOpts}),
  startDB, // we don't need the wrapper, we could use DB.start
  createUsers,
  createPost ], resolvedCallback);

If you are using some test framework (mocha/tape), you could initialize the database before all your tests and cleanup before start/after all tests.

cheers

Diazo answered 23/10, 2015 at 20:15 Comment(1)
Thanks. This is pretty much what I have done, only this hides a lot of the complexity as Post needs to reference the objects created in createUsers and of course the creation of multiple rows of data in createUsers also has to be run within async or equivalent.Insured

© 2022 - 2024 — McMap. All rights reserved.