EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)
一般我們在開發的時候,習慣上使用常規的關系型數據庫來設計數據庫表,對于一些業務表的字段比較固定的場景,是一種非常不錯的選擇,而且查詢的時候,由于是基于固定的表字段進行查詢,性能基本上是最優的。不過有一些場景下,業務信息的經常變化,使用常規的關系型數據庫來創建表字段、刪除字段的模式,肯定不是合適的處理方案,因此可能會進入JSON數據存儲的方式,而現今很多關系型數據庫也都支持JSON的存儲和子查詢處理,不過JSON的檢索還是比較麻煩,而且對于復雜的子查詢,性能據說也好不到哪里。而非關系型數據庫的NoSQL數據庫(MongoDB數據庫),它的產生就是為了解決大規模數據集合多重數據種類帶來的挑戰。結合關系型數據庫的熟練使用、性能優勢和MongoDB數據庫的彈性化文檔處理特點,我對EAV模型(實體-屬性-值)的設計和低代碼的處理方案提供一個實用的思路供參考。
1、數據庫 EAV 模型設計
如果我們要做一個電商的商品管理,我們先賣一些衣服,需要管理衣服的尺碼、顏色、款式等信息;有一天需要賣電腦了,電腦需要 主板、CPU、顯卡、內存、硬盤、散熱 等信息;過幾天又需要賣手機了,手機有 顏色、版本、存儲容量、套餐類型等等信息。數據庫的頻繁更改,可能會導致開發的復雜度增加,說不準要重新處理。
如果我們每次新增商品,需要支持不同的信息的話就不停的加字段。這樣會導致很多問題:
1、實現成本高,每次可能需要重新修改底層代碼,界面布局及相關處理等
2、性能越來越差,每次增加的字段,隨著復雜性越來越大,字段越來越多,導致性能急劇下降。
3、維護越來越難,沒有好的系統規劃,就如在沙堆上建設豪華城堡,隨著時間的推移,越來越難維護。
還有一種是采用JSON數據存儲方案,對于擴展的數據,可以統一存儲在某個JSON里面,這樣設計的擴展字段,可以有效屏蔽一些復雜度,并提高彈性化。如可以把 尺碼、顏色、款色、主板、CPU、顯卡、內存等等都放到 JSON 里。
不過這樣JSON數據存儲方案,對于更新和條件查詢來說,性能是比較差的,隨著數據量和復雜度的增加,這種響應效果肯定不如意的,對于大數據的處理,這種處理肯定是災難性的。
EAV(Entity-Attribute-Value)模型是一種靈活的數據庫設計方法,特別適合存儲具有可變屬性的實體。
- Entity:實體,代表一個業務對象,比如上面的例子里的商品。
- Attribute:對象的屬性,屬性并不是作為實體單獨的一列來進行存放,而是存儲在一組單獨的數據庫表中。
- Value:指特定屬性所關聯的值。
在電商商品管理系統中,商品的屬性可能會變化,因此EAV模型是一個合適的選擇。每個實體都有唯一的標識符,每個實體都可以有多個屬性與之關聯,每個屬性都有唯一的標識符,每個屬性都可以具有多個值。
以下是一個簡單的EAV模型設計示例:
實體表(Entity Table):
這里的實體是指商品。可能這里用實體類型表述更準確。

屬性表(Attribute Table):
這里的屬性是指商品的特征,例如顏色、尺寸等。

值表(Value Table):
這里存儲了實體和屬性的關聯,以及具體的屬性值。

這樣設計的好處在于,你可以靈活地添加新的屬性,而無需修改數據庫結構。然而,EAV模型也有一些缺點,例如查詢可能會更加復雜,因為需要在值表中進行屬性值的連接。
2、優化的EAV模型
對于上面屬性值的存儲,統一都采用字符串的方式來存儲,這樣對于類型的處理和空間節約肯定是不好的,因此我們需要進行優化,根據不同的類型存儲在不同的表上。
上面屬性值沒有類型限制,都是 VARCHAR 的,對數據庫不友好,會導致內存浪費,而且存取都需要進行數據格式轉換。對存儲為字符串的值創建的索引不允許針對數值型和日期型的搜索范圍優化,這是采用混合數據類型的鍵-值對描述數據的公共問題。
我們對屬性值表基于數據類型進行分割,每個不同的數據類型拆為一個單獨的表,同時通過 屬性表(Attribute) 添加 類型決定去哪里存取數據。

我們可以借鑒magento的eav模型,它是EAV設計的最優參考了。Magento 2中的EAV屬性類型有下面這些表:
- eav_entity_int
- eav_entity_varchar
- eav_entity_text
- eav_entity_decimal
- eav_entity_datetime
這5種屬性類型就相當于字段類型,一般關系型數據庫類型是通用的。
- int 對應字段的int類型
- varchar 對應字段的varchar類型
- text 對應字段的text類型
- decimal 對應字段的decimal類型
- datetime對應字段的datetime類型
這樣分別不同類型的數據進行不同表的存儲了。


其他的屬性類似的處理即可。
參考下eav的設計圖,了解一下各個表之間的關系。

以及magento的eav模型設計圖,復雜的令人抓狂。

3、NoSQL數據庫的登場
使用EAV(Entity-Attribute-Value)模式來存儲完整的數據結構信息以及NoSQL數據庫來存儲完整的記錄是一種靈活的方法,特別適用于需要存儲動態結構數據的場景。
EAV的常規關系型數據庫表存儲常規的設計表,如實體類型、屬性定義、屬性值(多個)表的相關信息,而利用MongoDB數據庫的大數據處理靈活性和高性能的響應,能夠存儲我們實際變化的文檔信息。在檢索的時候,并提供了常規關系型數據庫的聯合查詢、JSON查詢無法得到的靈活性和高性能。好馬配好鞍,雙劍合璧,簡直完美。
在介紹實現我們的EAV模型設計的過程前,我們先來看看實際的界面效果
1)實體類型表和屬性定義處理

我們新增實體類型的時候,只需要填寫簡單的信息和類名即可,如果對于產品的定義。

屬性定義,除了指定屬性的一些名稱、排序、默認值、屬性值存儲類型外,還可以設置是否為字典列表、或者從其他類型表中選擇等處理。

有了字段的定義,我們就可以在業務列表中顯示相關的字段,并從MongoDB總檢索指定類型的數據,由于MongoDB本身支持非常好的查詢處理,因此對于查詢來說非常簡單。
如對于產品定義和數據展示來說,我們動態創建的菜單,根據實體類型的ID就可以進行通用的查詢了。如下界面所示。

這個表的數據在MongoDB中存儲的,如下界面所示。

對于有主從表的業務處理,也是同樣的處理方式,除了顯示主表的信息外,還需要展示明細的記錄數據,我們通過整合關系型數據庫的EAV表和MongoDB的文檔記錄顯示,就可以很好的展示相關的數據了。

我們在訂單明細表中選擇表的設置,我們可以再明細表格中動態進行數據的選擇處理, 并可以設置關聯復制的屬性字段,如下界面所示。

訂單明細表的產品名稱屬性信息定義如下所示。

因為訂單明細表中,有時候需要復制來自產品信息的一些字段,我們在按鈕【設置其他復制字段】中處理映射關系即可。

這樣就可以自動引入選擇表的屬性值來填充了。
以上就是針對EAV模型設計,以及引入MongoDB來存儲詳細數據記錄,以便高效的查詢數據和處理動態化字段內容的需求。
有時間會繼續寫文章介紹詳細的實現過程,以及界面的動態化處理模式。
專注于代碼生成工具、.Net/Python 框架架構及軟件開發,以及各種Vue.js的前端技術應用。著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架、Python開發框架等框架產品。
??轉載請注明出處:撰寫人:伍華聰??http://www.iqidi.com?
????
浙公網安備 33010602011771號