【问题标题】:can we have one attribute with multiple values in an eav design?我们可以在 eav 设计中拥有一个具有多个值的属性吗?
【发布时间】:2011-01-27 23:38:15
【问题描述】:

我正在使用 EAV 进行数据库设计。当我尝试使用具有多个值的属性对实体建模时遇到问题?

例如

实体

id         | name           | description
--         | ----           | ------------ 
1          | configuration1 | configuration1

属性

id         | entityId    | name  | type
--         | --------    | ----  | ----
1          | 1           | att1  | string
2          | 1           | att2  | int
3          | 1           | att3  | List<String>  (How will i model this?)

价值

id        | attributeId    | value
--        | -----------    | -----
1         | 1              | a    
2         | 2              | 1
3         | 3              | b
4         | 3              | c    
5         | 3              | d

这是处理值列表的正确方法吗?

请提供任何有用的链接来对此进行建模?

还有两个问题

1) 类型为 List 是否正确?我想确定当一个属性有多个值时,我会将类型指定为 List

2) 当属性对应一个对象时,数据库设计将如何变化?例如用户有地址..我将如何处理复合参数?

如果你能提供一个粗略的表格表示或图表,那就太好了

谢谢

谢卡尔

【问题讨论】:

    标签: database-design entity-attribute-value


    【解决方案1】:

    是的!很可能在 EAV 中具有多值属性属性。
    事实上,它比传统的关系模型更容易,传统的关系模型需要创建一个额外的列,或者以排序的分隔格式存储多个值;在查询数据库以获取基础字段(属性)的给定值时,这两种方法都会增加复杂性。

    拥有多个值的最简单方法就是拥有一个额外的值记录! (如问题所示)
    此外,可以更改 EAV 存储结构以显式容纳多值,其中:

    • 属性表中一个额外的类似布尔值的字段,用于指示该字段是否可以是多值。 (顺便说一句,属性的类似属性也可以编码,例如是否需要该属性等
    • value 表可以得到一个额外的列来指示值的序列号(对于所有非多值属性设置为 0 或 1,否则为递增整数)。

    如上所述,这些对 EAV 存储的物理模式的更改不是必需的,但它们可用于确保数据符合(逻辑)模式以及可能显示多值属性的多个值按特定顺序等。

    编辑:(有关实现多值和/或复合(“类对象”)属性的详细信息)
    如果您绝对肯定构成属性的多个 ["sub"-] 值(或类似地构成“对象类型”属性的多个部分)是完全原子的,即永远不会被搜索或显示(或.. .) 单独地,您可以通过将多个值编码为单个字符串,将此类属性的值“集合”存储为值表中的单个记录;为此,我想到了 JSON 或 XML-at-large,并且对于非常可扩展/通用的来说似乎特别有趣,但任何其他可以以可靠方式解析进出的格式也可以工作(比如分隔格式)。

    存储此类“属性值部分”的一种更“自然”的方式(EAV 方式)是单独存储它们(在值表的多个记录中,可能带有如前所述的序列字段)。这种方法允许在某些情况下处理“子部分”,就好像它们是属性一样。

    在这两种情况下,您都需要更改属性表以添加必要的属性和类型代码,以描述此类多部分属性。与存储数据的方法(在值表中)类似,您可以制作属性记录,使得给定 [多部分] 属性的所有信息都存储在单个属性记录中,或者,[这是通常更容易和更灵活]您可以为每个部分创建一个属性,加上一个属性以“将它们绑定在一起”(例如,使用包含一个字符串的属性,该字符串由子部分的每个属性 ID 值分隔。

    例如
    金属管道项目的复合属性可以是直径,由两部分组成:数值单位代码(毫米,与英寸)。
    第一种方法:
    - 属性表中将有一条记录,其类型表明这是一个多值,以及一个扩展属性以包含各个子部分的 [有序] 类型列表。
    - 值表中会有一条记录,包含一个编码值,例如“0.75|Inch”(或&lt;diam&gt;0.75&lt;/diam&gt;&lt;unit&gt;Inch&lt;/unit&gt;)。
    第二种方法:
    - 属性表中将有 3 条记录:一条记录​​或数字类型并命名为“diamvalue”,一条字符串类型的记录,命名为“单位”,以及一条复合名称类型的记录“直径”;最后一条记录会以某种方式引用其他两个属性的 ID(想到一个简单的逗号分隔字符串) - 值表中有两条记录,直径值和单位属性各有一条(这些记录将有一个附加字段,称为“父”字段,其中包含“直径”属性的 AttributeID。可选地,还可以有一个“Diameter”属性的值记录[我个人认为这与“parent”属性是多余的。

    如前所述,第二种解决方案的主要优点是[在适当的时候]可以根据属性部分的值查询目录中的一组特定项目,例如搜索具有度量的所有管道单元。此类查询在 SQL 级别解析,第一种方法是,SQL 必须扫描属性“Diameter”的所有属性值并解析该值以搜索单位代码。

    一张图片胜过千言万语;-)
    此图显示了“第二种方法”的示例数据的可能布局。

    Entity 
        id   | name           | description
        --   | ----           | ------------ 
        1    | configuration1 | configuration1
    
    Attribute 
        id   | name      | type     | Required | Repeats | SubAttribIdList
        --   | ----      | ----     | -------- | ------- | ---------------
        1    | att1      | string   | N        | N       | null   (only applicable to composite types)
        2    | att2      | int      | Y        | N       | null
        3    | att3      | string   | Y        | Y       | null
        4    | DiamValue | numeric  | Y        | N       | null
        5    | Unit      | string   | Y        | N       | null
        6    | Diameter  | composite| N        | N       | 4,5
    
    Value
        id  | entityId| attributeId  | ParentAttribId |SeqNr | value     
        --  | --------| -----------  | -------------- |----- | -----
        1   | 1       | 1            | null           | 1    | a    
        2   | 1       | 2            | null           | 1    | 1
        3   | 1       | 3            | null           | 1    | b  (this value and next show show a repeating attribute)
        4   | 1       | 3            | null           | 2    | c    
        5   | 1       | 3            | null           | 3    | d
        6   | 1       | 4            | 6              | 1    | 0.75   (this value and next one shows a composite attribute
        7   | 1       | 5            | 6              | 1    | Inches
    

    一些注意事项:
    - 值 id 6 和 7 的 SeqNr 都是 1,对于两者。它们的顺序隐含在 SubAttribIdList 中。如果属性 id 6 已成为多值(“重复”)属性,则实体可以具有两个值的附加对联,按顺序排列、成对、2、3 等。
    - 不可重复属性的序列号系统地设置为 1,也可以设置为 NULL,这不适用。
    - 属性的“必填”属性不在多值或复合问题中;我刚刚添加了它,因为它通常用于帮助应用程序(或实体访问层)执行各种完整性规则。
    - 此布局中的一些设计选择意味着组合属性最多包含 1 级(组合不能包含在组合中),并防止组合包含多值属性。这些限制可以通过适当的结构来避免(并在访问层增加一点复杂性),但更简单的模式通常是可以接受的(需要这种花哨结构的属性通常表明逻辑模式存在缺陷) .

    【讨论】:

    • 感谢您的回答..我已经编辑了问题..请您提供答案
    • @Shekhar:我只是花时间“绘制”了一个可视化示例,说明多值和/或复合属性的存储方式。这样做时,我注意到 your 提议的架构中的一个错误:EntityID 字段属于值表,而不是属性表;这是不言而喻的(否则您将拥有几乎与值一样多的属性记录等),这可能是您在将架构转录到这种痛苦的空间格式布局时引入的错误。
    猜你喜欢
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    • 2012-05-27
    • 2011-01-25
    相关资源
    最近更新 更多