寻找基于jsonb的正确的EAV结构

Iva*_*nov 5 postgresql entity-attribute-value jsonb

我想知道在jsonb上构建EAV的正确方法是什么。我有Attribute-> Values表格,就像在标准EAV中一样。

CREATE TABLE attribute_values
(
  id           INTEGER,
  attribute_id INTEGER,
  value        VARCHAR(255)
);

CREATE TABLE attributes
(
  id   INTEGER,
  name VARCHAR(255)
);
Run Code Online (Sandbox Code Playgroud)

值将保存在attributes提起Entity

 CREATE TABLE entity
    (
      id   INTEGER,
      title TEXT,
      attributes JSONB
    );
Run Code Online (Sandbox Code Playgroud)

Attribute创建用于控制重复属性的表的类型,并更好地确定它是什么属性。例如,避免:{weight: 100}{Weight: 100}{weigh: 100}Values适用于使用唯一值并包含可用值列表,例如颜色(绿色,红色,白色等)。可以预加载值并将其用于常用搜索。

我看到几个选择:

1.存储格式如

[{"attribute_id":1, "value":5},{"attribute_id":1, value:"text"}] 
Run Code Online (Sandbox Code Playgroud)

这里value_id将是custom value像文字或idValues表。但我不明白如何建立索引的格式,例如,如果Attribute 10integer

2.仅保留Attribute表(用于控制attribute name)并存储数据,例如:

{"price": 105, "weight": 100, "color": "white"}
Run Code Online (Sandbox Code Playgroud)

。这种方法更好地建立索引

CREATE INDEX entity_index ON entity (((attributes ->> 'price')::int)); 
Run Code Online (Sandbox Code Playgroud)

但是我在翻译文本属性和控制唯一值方面会遇到问题。我也不能像option中那样添加其他键1{"attribute_id":1, "value":5, "values": []}

什么是存储具有唯一控件(用于唯一属性)并有机会进行索引的额外字段的最佳方法。

gah*_*ooa 7

目标:您要存储与给定实体相关的属性。

我不建议为属性值使用单独的表格,就像我们过去几年所做的那样。jsonb在适当的表上放一个字段,然后调用它AttributesGIN向其添加索引,以便您可以快速查询值。或使用其中描述的其他技术。

阅读此:https : //dba.stackexchange.com/a/174421/7762

这里最大的问题是您是否打算预定义属性值。如果您这样做,则有一种非常有效的方式来存储它们。如果没有,那么我建议使用标准的JSON对象。

如果可以预定义属性名称和值:

这为您提供了最大的控制,速度,并且仍然提供了灵活性。

创建一个Attribute包含以下字段的表:

  • AttributeID int4 unsigned not null primary key
  • ParentAttributeID int4 unsigned null
  • Name varchar(64) not null
  • Deleted bool不为null默认为false
  • 在上添加索引 ParentAttributeID
  • 添加触发器以防止AttributeID更改
  • 在删除操作上添加一条规则,而不是设置Deleted = True

然后在要归因的任何表中,添加以下字段:

这完成了什么?

您已经创建了属性树。它可能看起来像这样:

ID   Parent  Name
----------------------------
100  NULL    Color
101  100       Blue
102  100       Red
103  100       Green
110  NULL    Size
111  110       Large
112  110       Medium 
113  110       Small
Run Code Online (Sandbox Code Playgroud)

假设您有一个名为的表,Items并在上面添加了AttributeSet

      ItemID: 1234
        Name: Tee Shirt
AttributeSet: [100, 103, 110, 112]
Run Code Online (Sandbox Code Playgroud)

翻译后,这意味着它具有Color=Green属性和Size=Medium属性。 103并且112足以存储这些内容,但是有时候能够说出“显示所有定义了大小的所有商品”真是太好了,这就是为什么要包含110。

您可以使此闪电快速而又灵活。

SELECT
  "ItemID", "Name"
FROM
  "Items"
WHERE "AttributeMap" @> ARRAY[103,112]
Run Code Online (Sandbox Code Playgroud)

将返回所有具有Size=MediumColor=Green

或者,您可以使用https://www.postgresql.org/docs/10/static/functions-array.html上的其他运算符提出一些很棒的查询。

如果您不知道属性值,但是它是一个很小的集合:

这为您提供了最大的速度,控制力,并且更加灵活。如果需要,您可以标记新属性以供查看。

您可以使用上述技术,并在Attribute不存在的情况下将值动态添加到表中。

当您不知道属性值和值是否不同时

这为您提供了最大的灵活性,但是却以控制为代价。

在这种情况下,只需将其添加到任何表中:

  • AttributeMap jsonb not null default '{}'::jsonb
  • 将GIN索引添加到该字段

编写代码以对照Attribute表验证值。有一个指标是单值还是多值...

这样存储在AttributeMap现场:

{
    "Color": "Green", 
    "Size": "Medium", 
    "Categories": ["Sports", "Leisure"]
}
Run Code Online (Sandbox Code Playgroud)

请注意,类别是一个多属性。在youe Attribute表中,您应该具有一个字段,IsMulti bool not null该字段将使您知道如何查询它。