谈一谈自定义字段实现的几种方式

猎隼丶止戈 猎隼丶止戈 | 763 | 2022-09-06

前言

我们经常会遇到项目中很多对表单进行自定义,比如说 saas 应用针对租户自定义表单字段名称,自定义列表名称。

还有更高级自定义,比如说自定义的模块,表单、字段、字段类型、流程等自定义。

提供自定义也是一个系统扩展性的体现,自定义功能的强大自然能适应更多的用户场景。

接下来我们就看看自定义的实现方案通常都有哪些方式。

常见的自定义字段的实现方式分为三种由简到繁,扩展性、复杂性也是逐渐增强的,每个方式各有优劣解决的场景也有所不同,具体往下看。

列式存储自定义字段(扩展字段 ext field)

模型如下:

IDNameExt1(性别)Ext2(地区)Ext3(QQ)Ext4(WECHAT)
1韩梅梅Shanghai10000
2李磊Beijingabc001

优点:

  1. 实现成本最低
  2. 可以直接表连接进行检索

缺点:

  1. 扩展能力一般,有上限
  2. 浪费资源,比如说有 20 个扩展字段,一行只用到 2 个,其余的 18 个都要存储 null 来浪费空间。
  3. 能解决的场景比较有限。

EAV 模型 Entity-Attribute-Value(实体、属性、值)

对象属性存储在一个有三列的表中:实体,属性和值(entity,attribute,value)。实体(entiry)表示所描述的数据项,例如一个产品或汽车。属性(attribute)表示描述实体的数据,例如一个产品将有价格,重量和许多其他属性。值(value)是属性的值,例如产品可能有一个 9.99 英镑的价格属性。此外值可以基于数据类型进行分割,所以可将 EAV 表分为字符串、整数、日期和长文本(long text)表。依据数据类型分割是为了支持索引,使得数据库执行可能的类型检查验证。

EAV 表模型带来了数据的灵活性,是的增加对象的属性不需要用增加数据库的字段,有很高的灵活性。但是 EAV 表也有较大的性能问题。通常,EAV 表带来的一个问题是当查找多个字段时,需要进行关联查询 join,这样的查询效率比较低。为了提高查询效率,我们可以对商品属性表进行矩阵转积处理(pivoting)。

一种方式是在代码中读出后存入 cache 中,当修改 attributes 表后触发更新 cache 或用 cron 定期更新;另一种方法是将关联信息组成一张大的临时表,数据的更新可以用数据库的触发器触发更新。由于大量数据在代码中进行处理会带来了 DB 的额外 IO 和服务器性能问题。当使用 EAV 表模型时,InnoDB 比 MYISAM 的性能要好不少。

注:我们常用的行模型(纵向)存储就是 EAV 模型实现的一种方式。

模型如下:

人员表(Entity)

IDName
1韩梅梅
2李磊

扩展映射(Entities)

EntityAttributeValue
1sex(性别)
2sex(性别)
1region(地区)Shanghai
2region(地区)Beijing
1QQ10000
2WECHATabc001

优点:

  1. 扩展能力较强
  2. 理论上无上限
  3. 可以支持几乎所有的自定义字段的需求

缺点:

  1. 关联查询效率低下
  2. 需要维护自定义字段与值的关系表

Json 格式存储自定义字段

json 格式非常丰富,在描述自定义字段的这方面比较适合,可以把一行多列的数据压缩到一个 json text 内,也比较节省空间,json 格式可以无限扩展,还可支持多个自定义字段有不同的格式。

模型如下:

IDNameContent
1韩梅梅{“sex”:”女”,”region”:”Shanghai”,”QQ”:”10000”}
2李磊{“sex”:”女”,”region”:”Beijing”,”WECHAT”:”abc001”}

注:支持以上的两种不同的自定义格式并存

fc968d9185a643e7b199c5987beeb7ed.png

优点:

  1. 扩展能力强
  2. 理论上无上限
  3. 可以支持几乎所有的自定义字段的需求
  4. 无需维护自定义字段与值关系

缺点:

  1. 数据库需要支持 json type,不建议使用 text 类型
  2. 不支持关联查询(mongodb 除外)
  3. 自定义字段检索需要通过其他方式,例如搜索引擎。(mongodb 除外)

数据库对 Json 格式支持情况

数据库对 Json 类型的支持:

  1. Mysq5.7(CRUD 参考
  2. PostgreSQL(CRUD 参考json 与 jsonb 区别
  3. MongoDB(CRUD 参考

数据库对 json 类型的检索支持:

  1. Mysql5.7: 支持索引:通过虚拟列的功能可以对 JSON 中部分的数据进行索引。(相比 PG 和 MongoDB 弱一些,通过 json_extract()函数做一些简单查询)
  2. PostgreSQL:支持检索,可以复杂查询
  3. MongoDB:支持检索,可以复杂查询,支持 map reduce

ORM 框架对 Json 类型的支持:

  1. Mybatis 支持 json 格式字段映射到 POJO,方便 json 格式的 bean 与数据库映射。
  2. Hibernate 支持 json 格式字段映射到 POJO,方便 json 格式的 bean 与数据库映射。

Mysql5.7.x json 操作官方文档:

  1. json-creation-functions
  2. json-search-functions
  3. json-modification-functions

Mysql5.7.x 注意事项:

  1. JSON_UNQUOTE 、->、->> 之间的区别

    • 下面三个表达式返回相同的值

      1. JSON_UNQUOTE( JSON_EXTRACT(column, path) )
      2. JSON_UNQUOTE(column -> path)
      3. column->>path
  2. JSON_CONTAINS_PATH 参数说明

    • 第二个参数为 oneall 的区别

      1. one:至少存在一个路径返回 1,反之返回 0
      2. all:全部路径存在返回 1,反之返回 0
  3. JSON_CONTAINS 参数说明

    • 第二个参数是不接受整数的,无论 json 元素是整型还是字符串,否则会出现这个错误
  4. 5.7.x 不同版本支持的程度:

    • MySQL 5.7.13

      1. 支持操作符 ->>
    • MySQL 5.7.9

      1. 支持操作符 -> (JSON_EXTRACT()函数别名)
      2. 重命名函数 JSON_APPEND()为 JSON_ARRAY_APPEND(),函数作用:将值追加到 JSON 文档中指定数组的末尾并返回结果,未来会删除’JSON_APPEND()’
    • MySQL 5.7.22

      1. 支持 JSON_ARRAYAGG()返回 json 数组形式结果集,JSON_OBJECTAGG()返回 kson 对象形式结果集
      2. 添加 JSON_MERGE_PATCH(),作用:合并结果(相同 path)
      3. 添加 JSON_MERGE_PRESERVE(),作用:合并数据(不同 path)
      4. 弃用 JSON_MERGE(),使用 JSON_MERGE_PRESERVE() / JSON_MERGE_PATCH(),未来会删除’JSON_MERGE()’

实现方式不局限于上面说到的方式,有更好的方式欢迎留言进行沟通。

推荐指数:

转载声明:

原作者: 凝雨

转载自: 《谈一谈自定义字段实现的几种方式》,如有侵权,请联系本站删除。

真诚点赞 诚不我欺~

谈一谈自定义字段实现的几种方式

点赞 收藏 评论