一般我们在开发的时候,习惯上使用常规的关系型数据库来设计数据库表,对于一些业务表的字段比较固定的场景,是一种非常不错的选择,而且查询的时候,由于是基于固定的表字段进行查询,性能基本上是最优的。不过有一些场景下,业务信息的经常变化,使用常规的关系型数据库来创建表字段、删除字段的模式,肯定不是合适的处理方案,因此可能会进入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来存储详细数据记录,以便高效的查询数据和处理动态化字段内容的需求。

有时间会继续写文章介绍详细的实现过程,以及界面的动态化处理模式。

EAV模型(实体-属性-值)的设计和低代码的处理方案(1)的更多相关文章

  1. SQL反模式学习笔记6 支持可变属性【实体-属性-值】

    目标:支持可变属性 反模式:使用泛型属性表.这种设计成为实体-属性-值(EAV),也可叫做开放架构.名-值对. 优点:通过增加一张额外的表,可以有以下好处 (1)表中的列很少: (2)新增属性时,不需 ...

  2. IOS开发之动态获取模型的属性值

    #import "model.h" #import <objc/runtime.h> @implementation model +(instancetype)mode ...

  3. EAV模型

    了解EAV设计基本原理的最好方法就是理解行建模(row modelling,其中EAV是广义形式). 以一超市数据库为例,必须管理数以千计的产品和品牌,其中许多产品存在期很短暂.那么,显而易见,产品名 ...

  4. java怎么比较两个实体类的属性值

    分享一下比较两个实体类的工具包 package cn.mollie.utils; import java.beans.Introspector; import java.beans.PropertyD ...

  5. 反射 实现不同模型相同属性赋值 第二集(automapper)

    前言: 两年前写过一个 反射实现不同模型相同属性赋值 只能简单的实现两个model 相同属性名,相同类型赋值 最近又遇到这个问题,需要对相同属性名或者指定属性名 不同类型(复杂对象,如:List< ...

  6. Java反射之Bean修改更新属性值等工具类

    package com.bocean.util; import java.lang.annotation.Annotation; import java.lang.reflect.Field; imp ...

  7. webdriver高级应用- 改变一个页面对象的属性值

    适用于一些无法操作的元素,可以直接改他的属性从而操作,代码如下: #encoding=utf-8 from selenium import webdriver import unittest impo ...

  8. selenium--更改标签的属性值

    前戏 在进行web自动化的时候,我们有时需要获取元素的属性,有时需要添加,有时需要删除,这时候就要通过js来进行操作了 实战 from selenium import webdriver import ...

  9. webdriver高级应用 -更改一个对象界面的属性值

    #-*- coding=utf-8 -*- #更改一个对象界面的属性值 from selenium import webdriver import unittest def addAttribute( ...

  10. DDD 领域驱动设计-三个问题思考实体和值对象(续)

    上一篇:DDD 领域驱动设计-三个问题思考实体和值对象 说实话,整理现在这一篇博文的想法,在上一篇发布出来的时候就有了,但到现在才动起笔来,而且写之前又反复读了上一篇博文的内容及评论,然后去收集资料, ...

随机推荐

  1. #特征方程,dp,快速幂#洛谷 4451 [国家集训队]整数的lqp拆分

    题目 分析 设\(dp[n]\)表示答案,因为\(dp[n]=\sum\prod_{i=1}^mF_{a_i}\) \(dp[n]=\sum_{i=1}^{n-1}dp[i]*F_{n-i-1}\) ...

  2. C++调用Python-0:搭建环境

    1.进入到Python安装目录 2.将Python安装目录中的 include 和 libs 文件夹放在 C++项目中 3.设置 附加包含目录 和 附加库目录.附加依赖项(python310_d.li ...

  3. 资源池化支持同城dorado双集群切换(非日志合一)

    资源池化支持同城 dorado 双集群部署方式:dd 模拟(手动部署+无 cm).cm 模拟(手动部署 dd 模拟+有 cm).磁阵(手动部署).集群管理工具部署 1.集群间切换 基于<资源池化 ...

  4. 基于istio实现多集群流量治理

    本文分享自华为云社区<基于istio实现多集群流量治理>,作者: 可以交个朋友. 一 背景 对多云.混合云等异构基础设施的服务治理是Istio重点支持的场景之一.为了提高服务的可用性,避免 ...

  5. .NET周刊【4月第1期 2024-04-07】

    国内文章 一个程序员的编年史 https://www.cnblogs.com/lunacy/p/18117213 作者拥有15年软件开发经验,曾在多家公司工作,项目和团队起伏充满变数.2007年,在太 ...

  6. 【课程汇总】Hello HarmonyOS系列课程,手把手带你零基础入门

    HarmonyOS是面向未来.面向全场景的新一代智能终端操作系统,为不同设备的智能化.互联与协同提供了统一的语言,给人们带来简洁.流畅.连续.安全可靠的全场景交互体验. 初识HarmonyOS的开发者 ...

  7. 4A 安全之授权:编程的门禁,你能解开吗?

    概述 在安全管理系统里面,授权(Authorization)的概念常常是和认证(Authentication).账号(Account)和审计(Audit)一起出现的,并称之为 4A.就像上一文章提到的 ...

  8. Tkinter常用功能示例(一)

    技术背景 Tkinter是一个Python自带的GUI框架,虽然现在主流的还是用pyqt的多一些,但是Tkinter在环境配置上可以节省很多工作,可以用来做一些小项目.如果是大型项目,用pyqt或者Q ...

  9. springboot获取七牛云空间文件列表及下载功能

    原文摘自:https://www.codernav.com 第一步:新建springboot项目,引入jar包,其中hutool-all是工具类,用来写文件下载,可以随意更换. <!--工具类- ...

  10. vue 弹出框挂载富文本,富文本()无法实例化问题

    因为elementUI的dialog组件,他是v-if渲染,再页面刚加载时,这个弹出框还未进行挂载,我们就让他v-show显示. ,富文本实例再mounted里面挂载即可