Finding related mongodb document using Mongoose

82 views
Skip to first unread message

Donal Rafferty

unread,
Aug 31, 2015, 11:55:27 AM8/31/15
to Mongoose Node.JS ODM
I am currently dabbling in the MEAN stack and trying to learn as much as possible about MongoDB in particular and using the NodeJS Module Mongoose to interact with it.

I have followed initial tutorials and followed some of the best practices they mentioned with regards to relationships that are similar to one to many relationships in a relational DB.

This worked for my basic queries but now I have a query whereby the way I have setup the Schema's for the models doesn't really suit and I am trying to figure out the best way to do what I need.

My app has a RollerCoaster and a CoasterReview model, each RollerCoaster can have many CoasterReviews, so for this to work the tutorials suggested that when a CoasterReview gets created the ID of the RollerCoaster associated to it gets added to the CoasterReview model.

This approach works when I need to get a list of the CoasterReviews and populate the RollerCoaster for each CoasterReview within the model.

However I also have a need to get a list of RollerCoasters and also have the array of CoasterReviews per RollerCoaster populated within the returned list of RollerCoaster models.

Here's the RollerCoaster Schema:

Code:
/**
 * Rollercoaster Schema
 */
var RollercoasterSchema = new Schema({
    name: {
        type: String,
        default: '',
        required: 'Please fill Rollercoaster name',
        trim: true
    },
    created: {
        type: Date,
        default: Date.now
    },
});

And here's the CoasterReview schema:


Code:
/**
 * Coasterreview Schema
 */
var CoasterreviewSchema = new Schema({
    review: {
        type: String,
        default: '',
        required: 'Please fill Coasterreview review',
        trim: true
    },
    created: {
        type: Date,
        default: Date.now
    },
    rollercoaster: {
        type: Schema.ObjectId,
        ref: 'Rollercoaster'
    }
});

And here is what I have so far with trying to get a list of RollerCoasters that each have the array of CoasterReviews associated with them:


Code:
Rollercoaster.find(query).sort('-created').populate('userame').populate('themepark').exec(function(err, rollercoasters) {
        if (err) {
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        } else {
            //list of ids
            var rcIds = rollercoasters.map(function(el){return el._id;});
            //select all reviews with 'rollercoaster' = any _id from list
            CoasterReview
                .find({'rollercoaster':{$in:rcIds}}).sort('-created').exec(function(err, reviews) {
                    //res.jsonp(rollercoasters);
                    res.jsonp(reviews);
                });
        }
    });

This gives me the list of RollerCoasters and the list of Reviews separately, I could from here loop through the results and manipulate the JSON myself to get what I need but it feels like there is probably a better way to either structure the Schema's or to use Mongoose in a more efficient way.


Maybe I need to look into MapReduce?

Here is a what I want the resulting JSON to look like:

Code:
[
  {
    "_id": "55c2106227f2a878292a564d",
    "__v": 0,
    "created": "2015-08-05T13:32:18.473Z",
    "name": "Jurassic Park : The Ride",
    coasterreviews: [
    {
      "_id": "55dcbd9662a5516c39d27946",
      "rollercoaster": "55c2106227f2a878292a564d",
      "__v": 0,
      "created": "2015-08-25T19:10:14.392Z",
      "review": "The theming is fantastic"
    },
    {
        "_id": "55d8bb292d03db3c1310d465",
        "rollercoaster": "55c2106227f2a878292a564d",
        "__v": 0,
        "created": "2015-08-22T18:10:49.201Z",
        "review": "Woah what a ride, really thrilling and a great experience."
      }
    ]
  },
  {
    "_id": "55c20f0f27f2a878292a564c",
    "__v": 0,
    "created": "2015-08-05T13:26:39.055Z",
    "name": "Dragon Challenge : Hungarian Horntail",
    coasterreviews: [
      {
      "_id": "55d8d21908eda5a018c22ed4",
      "rollercoaster": "55c20f0f27f2a878292a564c",
      "__v": 0,
      "created": "2015-08-22T19:48:41.854Z",
      "review": "Great ride"
      }
    ]
  },
]

Can anyone help point me in the right direction for achieving this?

Rolando Rodriguez

unread,
Sep 3, 2015, 8:00:53 PM9/3/15
to Mongoose Node.JS ODM
Hi Donal,

This is my first time replying to this, I haven't even done this on stack overflow yet, but I'd recommend you use it. You get replies quick! 

So you're trying to have a rollercoaster have many coasterreviews, this is done with their 'embedded' way of doing things. The way you're doing it now is like creating a join table in a regular sql db. You want rolercoaster to own many reviews, this is embedded, one-to-many, and it is not many-to-many, which is what you're doing with using 'ref'

So in your rollercoaster model you're going to need to add the coasterreview schema, I would do it like this:

/**
 * Rollercoaster Schema
 */
var CoasterReview = require('CoasterReview.js')
var RollercoasterSchema = new Schema({
    name: {
        type: String,
        default: '',
        required: 'Please fill Rollercoaster name',
        trim: true
    },
    created: {
        type: Date,
        default: Date.now
    }, CoasterReview:[CoasterReview.schema]
});


Rolando Rodriguez

unread,
Sep 3, 2015, 8:02:12 PM9/3/15
to Mongoose Node.JS ODM
I'm so sorry it came out like this. This is my first time ever using google groups. I hope that helped. 
Reply all
Reply to author
Forward
0 new messages