4

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?

3 Answers 3

2

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.
});
Sign up to request clarification or add additional context in comments.

1 Comment

It seems this will simply return a single key with the document as its value, but not for the actual word entries (that will be plain objects, not key/value pairs). The stream simply gets one call to on('data'), with the whole document.
2
Word.find().lean().exec(function (err, docs) {
    // docs are plain javascript objects instead of model instances
});

1 Comment

But it still returns an array instead of a key-value object
1

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;
}, {});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.