Let's suppose I have a Word model with this schema
var Word = new Schema({
name: { type: String, required: true },
disambiguation: String,
partOfSpeech: { type: ObjectId, ref: "PartOfSpeech", required: true },
attributes: [{ type: ObjectId, ref: "Attribute"}],
root: [{ type: ObjectId, ref: "Word"}],
language: { type: ObjectId, ref: "Language", required: true }
});
I want to perform a query that returns an object, with word names as keys with and values as arrays of documents containing words with the corresponding name.
As an example, here is the sort of output I would like. Most fields are ommitted for brevity.
{
stick: [{
_id: "5024216f6df57b2b68834079",
partOfSpeech: "noun"
}, {
_id: "678451de6da54c2b68837345",
partOfSpeech: "verb"
}],
dog: [{
_id: "47cc67093475061e3d95369d",
partOfSpeech: "noun"
}]
}
This way, I can have random access to the list of words so I don't have to iterate over it repeatedly. Is there a built-in way to do this in mongoose?
Word.find().lean().exec(function (err, docs) {
// docs are plain javascript objects instead of model instances
});
You can't do this directly with Mongoose, but if you stream the results of a query you can build up your desired associative array pretty easily:
var stream = Word.find().stream(), results = {};
stream.on('data', function(doc) {
if (results.hasOwnProperty(doc.name)) {
results[doc.name].push(doc);
} else {
results[doc.name] = [doc];
}
}).on('error', function(doc) {
// Error handling...
}).on('close', function(doc) {
// All done, results object is ready.
});
You can use a reduce function to "re-index" any array into a dictionary. I use underscore reduce in my example, but I would think with a little tweaking it could work directly in mongoose. http://techishard.wordpress.com/2012/04/22/reducing-an-array-of-objects-to-a-hash-using-a-property-as-key/
_.reduce (foo, function (reduced, item) {
reduced[item.name] = item;
return reduced;
}, {});