Wow, that title is hard to read. OK, I'm stuck on something that should be really simple. I have a schema that looks like:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
TrackedVariableSchema = mongoose.model('TrackedVariable').schema;
var ChallengeSchema = new Schema({
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
trackedVariables: [TrackedVariableSchema],
entryConditions: [{
trackedVar: {
type: Schema.ObjectId,
ref: 'TrackedVariable'
},
comparison: {
type: String,
default: '=='
},
compValue: String
}]
});
mongoose.model('Challenge', ChallengeSchema);
And, TrackedVariableSchema looks like:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var types = 'Boolean String Number'.split(' ');
var TrackedVariableSchema = new Schema({
label: String,
type: {
type: String,
enum: types,
default: 'String'
},
defaultValue: String
});
mongoose.model('TrackedVariable', TrackedVariableSchema);
Each Challenge object maintains an internal list of TrackedVariables. (A 'TrackedVariable' is just a data definition for a datum that we want to track for that Challenge, but that's not very important.) I would prefer to keep TrackedVariables as an array of subdocs to their parent Challenge. I would prefer not to put them in their own collection.
My example is a little obscure, since these entity names won't make intuitive sense, but hopefully you can see what I am trying to do.
The problem comes when I findById() a single Challenge object, and want to see the label for each TrackedVariable of each Condition. Something like this:
{
"_id": "A1"
"title": "Make a Sandwich",
"trackedVariables": [{
"_id": "B1",
"label": "Slices of bread",
"type": "Number",
"default": "0"
}, {
"_id": "B2",
"label": "Has peanut butter",
"type": "Boolean",
"default": "false"
}, {
"_id": "B3",
"label": "Has jam",
"type": "Boolean",
"default": "false"
}],
"entryConditions": [{
"trackedVar": {
"_id": "B1",
"label": "Slices of bread",
"type": "Number",
"default": "0"
},
"comparison": ">=",
"compValue": "2"
}, {
"trackedVar": {
"_id": "B2",
"label": "Has peanut butter",
"type": "Boolean",
"default": "false"
},
"comparison": "==",
"compValue": "true"
}, {
"trackedVar": {
"_id": "B3",
"label": "Has jam",
"type": "Boolean",
"default": "false"
},
"comparison": "==",
"compValue": "true"
}]
}
Of course, the TrackedVariables aren't populated, so I get something like:
{
"_id": "5641adcc918df5901b1e1043",
"title": "Make a Sandwich"
"trackedVariables": [{
"_id": "12345",
"label": "Slices of bread",
"type": "Number",
"default": "0"
}, {
"_id": "23456",
"label": "Has peanut butter",
"type": "Boolean",
"default": "false"
}, {
"_id": "34567",
"label": "Has jam",
"type": "Boolean",
"default": "false"
}],
"entryConditions": [{
"trackedVar": "B1",
"comparison": ">=",
"compValue": "2"
}, {
"trackedVar": "B2",
"comparison": "==",
"compValue": "true"
}, {
"trackedVar": "B3",
"comparison": "==",
"compValue": "true"
}]
}
This won't do, because I need to produce a list that looks like:
Challenge entry requirements:
Entry Conditions for this Challenge
===================================
Slices of bread >= 2
Has peanut butter == true
Has jam == true
No problem. Just use populate(), right?
That's what I thought, too. And, if TrackedVariables were stored in their own collection (not as internal subdocs to a Challenge), this works just fine. But, nothing I've tried will give me the Challenge object with the TrackedVariable populated for each entryCondition.
I've tried pretty much every permutation of the following that I can think of:
Challenge.findById(id)
.populate('entryConditions.trackedVar')
.exec(function(err, challenge) {
...
...
No matter what I do along these lines, trackedVar always evaluates to either the id, or to null (depending on what I try). I suspect this has something to do with the fact that, in the response, the trackedVariables collections is already fully populated. And, to duplicate those data in the entryConditions collection, would be ... well ... a duplication.
I'm really stumped with this. Seems like it should be trivial.