Question

I'm new to Meteor and Mongo. Really digging both, but want to get feedback on something. I am digging into porting an app I made with Django over to Meteor and want to handle certain kinds of relations in a way that makes sense in Meteor. Given, I am more used to thinking about things in a Postgres way. So here goes.

Let's say I have three related collections: Locations, Beverages and Inventories. For this question though, I will only focus on the Locations and the Inventories. Here are the models as I've currently defined them:

Location:
   _id: "someID"
   beverages: 
      _id: "someID"
      fillTo: "87"
      name: "Beer"
      orderWhen: "87"
      startUnits: "87"
   name: "Second"
   number: "102"
   organization: "The Second One"

Inventories:
    _id: "someID"
        beverages:
            0: Object
            name: "Diet Coke"
            units: "88"
    location: "someID"
    timestamp: 1397622495615
    user_id: "someID"

But here is my dilemma, I often need to retrieve one or many Inventories documents and need to render the "fillTo", "orderWhen" and "startUnits" per beverage. Doing things the Mongodb way it looks like I should actually be embedding these properties as I store each Inventory. But that feels really non-DRY (and dirty).

On the other hand, it seems like a lot of effort & querying to render a table for each Inventory taken. I would need to go get each Inventory, then lookup "fillTo", "orderWhen" and "startUnits" per beverage per location then render these in a table (I'm not even sure how I'd do that well).

TIA for the feedback!

Was it helpful?

Solution

If you only need this for rendering purposes (i.e. no further queries), then you can use the transform hook like this:

var myAwesomeCursor = Inventories.find(/* selector */, {
  transform: function (doc) {
    _.each(doc.beverages, function (bev) {
      // use whatever method you want to receive these data,
      // possibly from some cache or even another collection
      // bev.fillTo = ...
      // bev.orderWhen = ...
      // bev.startUnits = ...
    }
  }
});

Now the myAwesomeCursor can be passed to each helper, and you're done.

OTHER TIPS

In your case you might find denormalizing the inventories so they are a property of locations could be the best option, especially since they are a one-to-many relationship. In MongoDB and several other document databases, denormalizing is often preferred because it requires fewer queries and updates. As you've noticed, joins are not supported and must be done manually. As apendua mentions, Meteor's transform callback is probably the best place for the joins to happen.

However, the inventories may contain many beverage records and could cause the location records to grow too large over time. I highly recommend reading this page in the MongoDB docs (and the rest of the docs, of course). Essentially, this is a complex decision that could eventually have important performance implications for your application. Both normalized and denormalized data models are valid options in MongoDB, and both have their pros and cons.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top