简体   繁体   中英

MongoDB many-to-many relationship logic

I'm trying to design a schema for Products , Suppliers and Manufacturers :

  1. A product can have many suppliers but only 1 manufacturer.
  2. A supplier can have many products and many manufacturers.
  3. A manufacturer can have many suppliers and many products.

I've reviewed this page where 10gen indicates "To avoid mutable, growing arrays, store the publisher reference inside the book document". In my example I consider the product-->manufacturer relationship to be equivalent to that of book-->publisher . I would therefore do this:

{
   _id: "widgets",
   manufacturer_name: "Widgets Inc.",
   founded: 1980,
   location: "CA"
}

{
   _id: 123456789,
   product_name: "Steel Widget",
   color: "Steel",
   manufacturer_id: "widgets"
}

{
   _id: 223456789,
   product_name: "White Widget",
   color: "White",
   manufacturer_id: "widgets"
}    

What is the best way to handle the SUPPLIER (with relationships to many products and many manufacturers) such that I "avoid mutable, growing arrays"??

Note: This is one way to model it. Data modeling has a lot to do with the use cases and the according questions you want to ask. Your use case might need a different model.

I'd probably model it like this

manufacturer

{
  _id:"ACME",
  name: "ACME Corporation"
  …
}

products

{
  _id:ObjectId(...),
  manufacturer: "ACME",
  name: "SuperFoo",
  description: "Without SuperFoo, you can't bar or baz!",
  …
}

Now comes the problem. Since potentially, if we embed all the products in a supplier document or vice versa, we could break the 16MB size limit easily, I'd use a different approach:

Supplier:

{
  _id:ObjectId(...),
  "name": "FooMart",
  "location: { city:"Cologne",state:"MN",country:"US",geo:[44.770833,-93.783056]}
}

productSuppliers:

{
  _id:ObjectId(...),
  product:ObjectId(...),
  supplier:ObjectId(...)
}

This way, each product can have gazillions of suppliers. Now here come the drawbacks.

For finding a supplier for a certain product, you have to do a two step query. First, you have to find all supplier IDs for a given product:

db.productSuppliers.find({product:<some ObjectId>},{_id:0,supplier:1})

Now, let's say we want to find all suppliers of SuperFoo near Cologne,MN at a max distance of 10 miles:

db.suppliers.find({
  _id:{$in:[<ObjectIds of suppliers from the first query>]},
  "location.geo": { $near :
    {
      $geometry: { type: "Point",  coordinates: [ 44.770833, -93.783056] },
      $maxDistance: 16093
    }
  }

})

You need to do quite some smart indexing to make these queries efficient. Which indices you need depends on your use case. The problem with indices is that they are only efficient when kept in RAM. So you really should be careful when creating your indices.

Again: The way you model data heavily depends on your use cases. In case you only have a few products per manufacturer or only a few suppliers per product or if each supplier only supplies products by a certain manufacturer, the model may look quite different.

Please have a close look at MongoDB's data modeling documentation . Most problems with MongoDB stem from wrong data modeling for the respective use case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM