哪種模式更適合購物項目?
我正在從事具有多種產品類型的企業對客戶項目。每個產品都有一些屬性,如名稱、描述、brand_id,但也有許多針對不同產品的專用屬性。
我正在尋找一種合理的解決方案來處理手機和空調等不同類型的產品。例如,手機具有稱為 CPU 的屬性,而空調則沒有該屬性。此外,空調具有稱為 BTU 的屬性,而手機沒有 BTU 之類的屬性。
我想做的是一個經典的基於類別的產品系統。使用者將能夠創建包含不同欄位的類別,例如 BTU 的 CPU,並且當他們想要創建產品時,他們將能夠為該產品輸入這些欄位的值。
在 SQL 世界中,我看到許多項目使用這樣的模式:
products -> (id, name, brand_id, description, category_id) categories -> (id, name) category_fields -> (id, category_id, field_name, field_type) product_fields -> (product_id, category_field_id, value)
但是我想知道這個問題是否有更好的解決方案。我想到了兩種不同的解決方案。
products -> (id, name, brand_id, description, category_id, (json) category_values) categories -> (id, name) category_fields -> (id, category_id, field_name, field_type)
您可能會注意到 products 表中有一個名為 category_values 的列。此列是 JSON 類型(Postgresql 有),我將索引我需要搜尋的鍵。
另一個架構:
products -> (id, name, brand_id, description, category_table) products_cellphones -> (product_id, memory, cpu, gps ...) products_...
在此模式中,當使用者創建類別時,系統將在執行時在數據庫中創建一個包含其欄位的新表。我將創建一個動態生成 sql 選擇並執行它們的視圖。
我應該選擇哪種方式,或者您有其他解決方案嗎?
對產品功能目錄使用 EAV(實體屬性值)方法會好得多。該方法可傳輸到任何 SQL 平台,因為它不依賴 Postgresql 的特定功能(JSON 列)。
所有反對 EAV 的常見論點都不適用於產品特徵目錄,因為產品特徵值通常只會反芻到列表中,或者最壞情況下到比較表中。
使用 JSON 列類型使您能夠從數據庫中強制執行任何數據約束並將其強製到您的應用程序邏輯中。此外,為每個類別使用一個屬性表具有以下缺點:
- 如果您最終擁有數百個(或更多)類別,則它無法很好地擴展。
- 如果您更改類別的允許屬性,則必須更改表定義,而不僅僅是在其中添加或刪除行
category_fields
- 如果產品具有許多潛在功能,但其中只有一小部分是已知的,那麼您最終可能仍會得到填充稀疏的表格。
檢索有關具有特定功能的產品的數據並不是特別困難。可以說,使用 EAV 模型創建動態 SQL 比使用 table-per-category 模型更容易。在每個類別的表中,您需要反射(或您的 JSON)來找出特徵列名稱是什麼。然後,您可以為 where 子句建構項目列表。在 EAV 模型中, WHERE X AND Y AND Z變成了 INNER JOIN X INNER JOIN Y INNER JOIN Z,所以查詢稍微複雜一些,但是建構查詢的邏輯仍然是完全表驅動的,而且會更如果您建構了正確的索引,那麼它的可擴展性就足夠了。
有很多理由不將 EAV 用作一般方法。這些原因不適用於產品功能目錄,因此 EAV 在此特定應用中沒有任何問題。