質問

I understand that it is generally considered a "bad idea" to store JSON in a MySQL column due to the fact that it becomes difficult to maintain and is not easily searched, or otherwise queried. However, I feel that the scenario I have encountered in my application is a reasonable use case for storing JSON data in my MySQL table. I am indeed looking for an answer, particularly one that may point out any difficulties which I may have overlooked, or if there is any good reason to avoid what I have planned and if so, an alternate approach.

The application at hand provides resource and inventory management, and supports building Assemblies, which may contain an infinite number of sub assemblies.

I have a table which holds all of the metadata for items, such as their name, sku, retail price, dimensions, and most importantly to this question: the item type. An item can either be a part or an assembly. For items defined as assemblies, their contents are stored in another table, item_assembly_contents whose structure is rather expected, using a parent_id column to link the children to the parent. As you may expect, at any time, a user may decide to add or remove an item from an assembly, or otherwise modify the assembly contents or delete it entirely.

Here is a visual representation of the above table description, populated with data that when composed, creates an assembly containing another assembly. Item and Assembly Table Structure With the above structure, any item that is deleted from the items table will also be automatically deleted in the item_assembly_contents table via InnoDB ON DELETE CASCADE.

Here is a very simple example Assembly in JSON format, demonstrating a single Sub Assembly structure.

{
   "id":1,
   "name":"Fruit Basket",
   "type":"assembly",
   "contents":[
      {
     "id":10,
     "parent_id":1,
     "name":"Apple",
     "type":"part",
     "quantity":1
      },
      {
     "id":11,
     "parent_id":1,
     "name":"Orange",
     "type":"part",
     "quantity":1
      },
      {
     "id":12,
     "parent_id":1,
     "name":"Bag-o-Grapes",
     "type":"assembly",
     "quantity":1,
     "contents":[
        {
           "id":100,
           "parent_id":12,
           "name":"Green Grape",
           "quanity":10,
           "type":"part"
        },
        {
           "id":101,
           "parent_id":12,
           "name":"Purple Grape",
           "quanity":10,
           "type":"part"
        }
     ]
      }
   ]
}

The Fruit Basket is an Assembly, which contains a Sub-Assembly named "Bag o Grapes". This all works wonderfully, until orders and shipments come into consideration.

Take for example, an outbound shipment containing an assembly. At any time, the user must be able to see the contents of the assembly, as they were defined at the time of shipment, which rules out simply retrieving the data from the items and item_assembly_contents table, as these tables may have been modified since the shipment was created. Therefore, assembly contents must be explicitly saved with the shipment so that they may be viewed at a later date, independent of the state or mere existence of the assembly in the user's defined inventory (that being, the items table).

It is storing the assembly contents along side the shipment contents that has me a bit confused, and where it seems to me that storing the data in JSON is a visable solution. It is critical to understand the following points about this data:

  1. It will NOT be used for Searches
  2. Any UPDATES will simply overwrite the contents of the row
  3. It will MOST OFTEN be used to populate a Tree View on the Client, which will accept the JSON as it exists in the table, without any need for modification.

See this image for a (hopefully) more clear visualization of the data: Current vs Proposed Table Structure

Questions

  1. Is this a reasonable use case? Are my concerns meaningless?
  2. Is there anything that I have looked over that may come back to bite me?
  3. Can you provide an explanation why I should NOT proceed with my proposed schema, and if so....
  4. Can you provide an alternative approach?

As always, thank you so much for your time and please do not hesitate to request clarification or additional information.

UPDATE As per @Rowland Shaw's suggestion (below), I've come up with another proposed table structure using a reflexive or "bunny ear" relationship to the order_assembly_contents table. Please see the following image: Updated Proposed Table Structure

I feel this is a lot more elegant than storing the JSON directly, as the data is more relational and database friendly. Retrieving the data and forming it for the client should be easy-peasy as well! Please provide any input on the above structure!

役に立ちましたか?

解決

Typically, for an ordering system I'd expect something like

Product -< OrderLine >- Order

In your case, you could add a "bunny ear" relation on your Product to refer to itself. So your outbound_shipment_contents loses name, type to the new product. You can then recursively build up the tree of items to pick as required.

他のヒント

This appears to be a standard bill of materials problem and there are lots of good articles on SQL and bill of materials patterns. I would avoid the JSON storage as it really complicates any reporting and detailed joining functionality that relies on the native SQL. For your application you can construct the JSON for the UI within a data access layer.

IMHO: Keep the data clean, highly accessible and relational in the relational db, repurpose for the application at the data access/low level business layer.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top