Best practice for simple mongo relationships


#1

Here’s the hypothetical situation.

  • I have a collection called books
  • a salesman (registered user) can sell a customer books. When a book is sold a receipt is emailed by the salesman to the customer.
  • the salesman can resend a receipt only, not update or remove and can only view receipts they have submitted
  • managers need to be able to see ALL receipts that have been sent by all users.

What is the best practice for relating the salesman to their receipts? Do I add the receipts as a child of the user document? Or insert a new document in the receipt collection adding the salesman’s user id?

I’m using autoform if that makes any difference. Just starting out it seems to make a difference to me because getting into document children seems a little intimidating in regards to autoform.


#2

I don’t think there is a best practice. Your design should be based on how you will query your database and publish your data.
In your specific case (many-to-one relationship), I suggest you start by storing the salesman’s user id in the receipt collection. Then, write your publish functions and main queries (pseudo-code), and see if it goes nicely. If it doesn’t, try the other way.


#3

You have to reason in terms of n-to-n relationships rather than in terms of how data flows in your app.
e.g Can a book be sold by multiple salesmen? Can salesmen have multiple managers? And so on…

In general:
- embed when 1-to-1 and 1-to-many relationships.
- reference (normalize) when many-to-many relationships.

But do check mongo docs on this :wink:


#4

@simo7 embedding usually results in de-normalizing, whereas referencing is the opposite… i think you should make yourself clearer for the OP


#5

presuming you need to access receipts on both ends (both customers and salesmen/managers would like to view receipt history,)
embedding the receipts in either customer or salesman collection depends substantially on your access pattern -
which end has more frequent access to the receipts?

if performance is crucial and you believe embedding would be advantageous to your access patterns, then be prepared for more complex code with extra caution required in Meteor (i.e. publishing sub documents / arrays )

otherwise, setting up an independent collection of receipts, with the customer and salesmen collections storing reference keys to it, may just be a convenient yet practical solution (especially with Meteor reactivity preferring top-level schemas)

Just keep in mind MongoDB is very powerful, and it just keeps improving (WiredTiger), so while I have no solid data to support my belief, I believe that a normalized form is unlikely to hinder this typical use case


#6

Thank you for your responses. This isn’t a high volume app. I used the books and salesman because it’s the easiest way I could describe it but realize it may have been a little off. Really what’s happening is this app is used as a small marketing tool for sales reps who sell air con/heating service. The client (air con company) offers and hypes up their warranties and guarantees. Each one can be purchased based on what service was performed etc. So the sales rep uses the app to “check” off which guarantees the customer has chosen, then emails the customer a copy of their full warranty with the chosen guarantees. So I guess using the example above, each book is unique, once a salesman sells it, it’s sold. The managers need to audit and keep track so they’d be in there much more than a salesman. I just figured if I’m making it where a sales rep has to register anyways to be able to send the receipt, then why not give them access to review their previous submissions and/or resend the receipt. I don’t see the sales rep using the backend as much as managers.

To me coming from MySQL, php…it seems easier to just keep a separate collection for receipts and reference the sales rep id…but just because it’s easy doesn’t mean it’s the proper way and I’m not looking for the easy way out per-se.

Thanks again for your input.


#7

with this further information, I now have a firm opinion it should be relational

having 3 actors (salesmen, customers and managers,) I advise you to go on neutral grounds and store a receipts collection, which would give you easy access for all actors

while NoSQL offers the non relational alternative, it’s not necessary or required, especially with MongoDB being a document store model


#8

Thanks, missed that one did not re-read, edited!