Mongoose schema within schema

As of version 4.2.0, mongoose supports single subdocuments.

From the docs:

var childSchema = new Schema({ name: 'string' });

var parentSchema = new Schema({
  // Array of subdocuments
  children: [childSchema],
  // Single nested subdocuments. Caveat: single nested subdocs only work
  // in mongoose >= 4.2.0
  child: childSchema
});

There are a few ways to do this. The simplest is just this:

var TaskSchema = new Schema({
    name            : String,
    lastPerformed   : Date,
    folder          : String,
    user            : Schema.ObjectId
});

Then you just have to make sure your app is writing that id and using it in queries to fetch "related" data as necessary.

This is fine when searching tasks by user id, but more cumbersome when querying the user by task id:

// Get tasks with user id
Task.find({user: user_id}, function(err, tasks) {...});

// Get user from task id
Task.findById(id, function(err, task) {
  User.findById(task.user, function(err, user) {
    // do stuff with user
  }
}

Another way is to take advantage of Mongoose's populate feature to simplify your queries. To get this, you could do the following:

var UserSchema = new Schema({
    name        : String,
    app_key     : String,
    app_secret  : String,
    tasks       : [{type: Schema.ObjectId, ref: 'Task'}] // assuming you name your model Task
});

var TaskSchema = new Schema({
    name            : String,
    lastPerformed   : Date,
    folder          : String,
    user            : {type: Schema.ObjectId, ref: 'User'} // assuming you name your model User
});

With this, your query for all users, including arrays of their tasks might be:

User.find({}).populate('tasks').run(function(err, users) {
  // do something
});

Of course, this means maintaining the ids in both places. If that bothers you, it may be best to stick to the first method and just get used to writing more complex (but still simple enough) queries.


What about this simple solution?

var TaskSchema = new Schema({
    name            : String,
    lastPerformed   : Date,
    folder          : String,
    user            : {
        name        : String,
        app_key     : String,
        app_secret  : String
    }
 })