V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
itechnology
V2EX  ›  程序员

怎么设计一张表来保存数字区间和单选类型的配置数据?

  •  
  •   itechnology · 2023-05-07 21:58:51 +08:00 · 1688 次点击
    这是一个创建于 569 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在遇到一个需求需要保存一些标准配置,这些标准配置是可以在页面动态配置的,所以需要保存到数据库里,这些标准配置分为两种类型,数字区间类型和单选类型:

    一:数字区间类型:比如对于层高,在页面上可以将任意数字区间设为标准或者非标准,比如设置大于等于 2.4 且小于等于 2.8 属于标准。而数字区间会涉及开闭区间问题,所以会存在四种情况:[2.4,2.8],(2.4,2.8),(2.4,2.8],[2.4,2.8)。

    二、单选类型:比如对于产权性质,可能会存在国有房产、私有房产、集体所有房产、股份制企业房产、联营企业房产等选项,在页面上可以把任意一个选项设为标准或者非标准。

    如何设计一张表同时保存这两种情况的数据?

    第 1 条附言  ·  2023-05-07 23:03:25 +08:00
    要求是保存到 MySQL 数据库中
    11 条回复    2023-05-08 09:29:52 +08:00
    lmshl
        1
    lmshl  
       2023-05-07 22:19:06 +08:00
    JSONB
    这种东西会无穷无尽的,我建议你直接上文档型字段
    k9990009
        2
    k9990009  
       2023-05-07 22:21:32 +08:00 via Android
    json 。这种后端没有逻辑,单纯前端用的。又没很高的查询需求,随前端折腾。
    itechnology
        3
    itechnology  
    OP
       2023-05-07 22:27:34 +08:00
    @k9990009 后端需要用到这些配置。用来判断一些数据是标准还是非标准。
    fkverexadmin
        4
    fkverexadmin  
       2023-05-07 22:57:23 +08:00 via Android
    mongodb 一把梭哈
    clf
        5
    clf  
       2023-05-07 23:00:02 +08:00
    我大概写过这样的东西。用于校验字段是否在合理范围内。

    数字区间我参考了 google 的 guava 的 Range 对象以及 hutool 里的 Range 对象。

    Range 里有 2 个数值和两个布尔用于标记边界值以及开闭情况。同时还有一个 Map<String,Double>用于储存一些文本对应的数值(满足可比较的带有等级含义的中文文本的范围)

    存储因为后端是 mongo 可以直接存。如果你要用 mysql 等数据库存,map 结构可以拆一张关系表,或者 json 。

    _________

    假设 ABCDE 五个等级,你标记的范围是 B-E ,那么存储的数据大概是(字段名字随便取的,能看懂就行,实际取名建议抄 guava 的字段命名):

    start:1,end:4,startOpen:false,endOpen:false,config:{A:0,B:1,C:2,D:3,E:4}

    或者是拆 2 张表:
    范围表 range
    id:id1,start:1,end:4,startOpen:false,endOpen:false

    配置表 range_config
    range_id:id1,label:A,value:0
    ……
    itechnology
        6
    itechnology  
    OP
       2023-05-07 23:03:58 +08:00
    @clf 好的谢谢你提供的思路
    GeruzoniAnsasu
        7
    GeruzoniAnsasu  
       2023-05-07 23:12:34 +08:00
    虽然这么说有点不太尊重,先道个歉…… 但我每次看到这种无法把需求抽象成概括性问题的帖总会觉得,这人想不出做法是一点也不冤。


    首先要考虑的问题:这些数据谁来处理?可计算吗?向量维度是可变的吗



    --------

    比如你提的第一个需求,假设(反正你没说清)这种数字区间是用来做判断的,比如系统有个功能叫「设定标准」,标准=一组区间。那么是否存在 「判断(判断即计算,因为必然存在算数过程)给定输入是否符合已定义的标准」 的功能?如果有,是你负责的部分要进行这个判断,还是你只是在做数据持久化的中间件,你只关心数据的序列化形式不关心它的解析?向量维度的意思是,一个「标准」是否固定地只有上下界两个参数,还是有一个复杂的关联,包含了一系列数字区间?

    如果一个条目里(或者你打算设计的表,一行中)只存在唯一一个区间,那显然只需要两个代表上下界的数字和两个代表开闭区间的逻辑符号即可,简单地 4 个列就能完成需求。或者更学究一点可以用 mask 数字来代表逻辑符号。

    但如果「标准」这个条目和「区间数量」的关系是不确定的,一个条目中能关联任意多个不同区间,那显然不可能只用一张表实现。视乎具体需求的复杂度,可能需要

    - 表 A ,保存「标准」的 id
    - 表 B ,保存定义「标准」时可用的项目枚举,如「层高」=1 、「面积」=2
    - 表 C ,保存「标准」包含的条目关系,如 [标准 id,项目枚举 id, 逻辑符号, 数字],[1,1,>,2.5],[1,1,<=,4],[1,2,>,10]

    上述例子就表示 id=1 的「标准」包含 ( 2.5<层高<=4 且 面积>10 )两组区间

    当然了,如果系统中不存在判断「是否符合标准 1 」的场景,那上述这些设计并不是必要的,甚至于假如处理数据的主体并不直接与数据库交互,它接收的是某种中间表示,那完全可以直接把它的结构化表示作为字符串存进数据库里,如 json {id:1, name:"标准 1", rules:[{"层高":[">2.5","<=4"]},{"面积":[">10"]}]}


    --------

    第二个要考虑的问题: 你真的是想「保存单选类型的数据」?

    单说这个抽象后的问题「如何把 options 存进数据库」,那任何但凡有程序思维(他不用会写)的人都能想到用枚举表示 options ,然后把枚举值存起来即可,最多再额外存一下枚举值和字面表示的对应(如果不在代码里写死的话)。如果你遇到的是类似「如何保存非预定义(可任意新建和自定义)的枚举」的问题。那么这个答案是「字典表」。如果不是,那么你的第二条说明就不仅没能概括问题,还表述了完全错误的方向


    还有第三个问题: 为什么要把区间和 option 枚举两个看不出逻辑关系的东西,糅合进同一个表里?在你的问题里并没有体现仅用一个表来同时完成两个需求的必要性。如果有,那能不能解释一下这个表的 primary key 是什么? 为什么上述两个「配置」都会与这个 key 唯一对应?


    p.s.题外话,突然发现软件工程那些没人在意的 UML 建模什么的,或许还真的对某些特定场景有帮助,比如当你想不出业务里的对象关系时
    itechnology
        8
    itechnology  
    OP
       2023-05-07 23:44:51 +08:00
    @GeruzoniAnsasu 我本意是只想问问怎么保存这些数据到 MySQL 数据库的,所以很多东西都没说的很清楚,既然你说起,我就描述详细一点:

    背景是这样的,前端页面会录入楼栋的一些属性数据,这些属性分为两种类型,数字输入类型和下拉单选类型,这些属性的值都要求前端判断是标准还是非标准,同时为了保险起见,在用户点击保存时,后端需要重新判断这些属性的值是标准还是非标准的,而怎么定义为标准 /非标准呢,就是通过一个配置页面去配置的,他们的配置方式如下:

    对于数字输入类型,我可以为某一个属性设定多个标准的数字区间和多个非标准的数字区间,比如我可以同时将[2,4]、(6,7]、(9,10)设置为标准,在配置页面上展示时[2,4]、(6,7]、( 9,10 )是三条数据。同理,我也可以同时设置[12,14]、(16,20]设置为非标准,他们在配置页面展示时是两条数据。理论上某一个属性的标准和非标准区间可以有无数个。

    对于下拉单选类型,因为某一个属性的下拉单选项是固定的,所以某个属性在配置页面展示的条数是固定的。在配置页面只需要将对应的选项标准或者非标准就行了。

    现在想请教的问题是怎么保存这个配置页的数据,从而方便前端和后端去判断录入楼栋的一些属性数据是标准还是非标准?
    GeruzoniAnsasu
        9
    GeruzoniAnsasu  
       2023-05-08 08:02:31 +08:00
    @itechnology

    如果要存进 mysql 里,那隐含的含义就是,这些数据是要相互建立查询关系的。如果确实如此,那我真建议先用 UML/ER 之类的图表辅助手段搞清楚每个对象主体包含哪些字段,字段和实体的相互关系如何(多对一?一对多?)


    我前面的回复给了一个保存多区间(实际上是保存二元判定函数)的例子,那个方法可以保存由任意多简单逻辑组合成的二元判定。

    但直到目前的描述我还是不确定你是否遇到的是需要保存任意复杂二元判定的场景。「标准」是否是一个可保存的实体(意味着很可能需要一个以「标准」作为 primary key 的表)?还是实体上的 bool 字段(意味着要先搞清楚哪个实体要保存「是否标准」这个字段)?


    而且当你把两个问题放在一起的时候就更显得迷惑,如果按照问题 1 的描述,系统模型应该是前者,一个属性对应一个「标准」对象和一个「非标准」对象,每个标准 /非标准对象对应若干由逻辑符号(开 /闭)和数字组成的判例;而问题 2 中又在描述一个属性对应若干但固定数量的判断,每个判断是一个标准 /not 标准的二元结论,这描述的就是后者的场景。




    或者可以不直接从数据库层面考虑,程序面向对象的建模与数据库建模是完全一致的,代码里的 class 对应数据库中的表,class 的字段对应表中的列,如果程序中对这些结构已经有良好定义的表示,照着 orm 的思路抄进数据库里就完事了,如果程序也还不能处理,那完全可以先尝试把不落库的逻辑实现出来,这是可以反复实验的,等代码模型可以用了再转化成数据库模型。
    itechnology
        10
    itechnology  
    OP
       2023-05-08 09:15:16 +08:00
    @GeruzoniAnsasu 我已经说的这么详细了,你还不明白的话,那我就没办法了。
    mingl0280
        11
    mingl0280  
       2023-05-08 09:29:52 +08:00 via Android
    @itechnology 我看了下你的详细需求……上 mongodb 或者其它文档存储吧,sql 几乎无法满足你这个需求。除非你把数据当 json 存 sql 里……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2027 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:17 · PVG 00:17 · LAX 08:17 · JFK 11:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.