基于jsonb寻找合适的EAV结构

Looking for a right EAV structure based on jsonb

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

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

CREATE TABLE attributes
(
  id   INTEGER,
  name VARCHAR(255)
);

值将保存在 Entity

attributes 字段中
 CREATE TABLE entity
    (
      id   INTEGER,
      title TEXT,
      attributes JSONB
    );

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

我看到几个选项:

1. 存储格式如

[{"attribute_id":1, "value":5},{"attribute_id":1, value:"text"}] 

其中 value_idcustom value 类似于文本或 id 来自 Values table。但是我不明白如何在这种格式上建立索引,例如 if Attribute 10 will integer

2.只保留Attributetable(用于控制属性name)并存储数据如:

{"price": 105, "weight": 100, "color": "white"}

。这种方法更适合索引

CREATE INDEX entity_index ON entity (((attributes ->> 'price')::int)); 

但我在翻译文本 属性 和控制唯一值时遇到问题。我也不能像选项 1 那样添加额外的键:{"attribute_id":1, "value":5, "values": []}

存储具有唯一控制(对于唯一属性)和索引机会的额外字段的最佳方法是什么。

Objective:您想存储与给定实体相关的属性。

我不建议像过去几年那样为属性值单独 table。在适当的 table 上放置一个 jsonb 字段并将其命名为 Attributes。为其添加一个 GIN 索引,以便您可以快速查询值。或者使用其中描述的其他技术。

读这个:https://dba.stackexchange.com/a/174421/7762

这里最大的问题是您是否打算 pre-define 属性值。如果这样做,有一种非常有效的方法来存储它们。如果没有,那么我推荐一个标准的 JSON 对象。

如果可以 pre-define 您的属性名称和值:

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

创建一个 table Attribute,其中包含以下字段:

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

然后在任何你想要属性的table中,添加这个字段:

这有什么成就?

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

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

假设您有一个名为 Items 的 table 并在其上添加了 AttributeSet:

      ItemID: 1234
        Name: Tee Shirt
AttributeSet: [100, 103, 110, 112]

翻译后,这意味着它具有 Color=Green 属性和 Size=Medium 属性。 103112 足以存储它,但有时能够说“显示所有定义了任何尺寸的项目”是很好的,这就是为什么包含 110。

你可以让这个闪电般的快速和超灵活。

SELECT
  "ItemID", "Name"
FROM
  "Items"
WHERE "AttributeMap" @> ARRAY[103,112]

将 return 所有具有 Size=MediumColor=Green

的项目

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

当您不知道属性值但它是一个小集合时:

这给你最大的速度、控制力,甚至更灵活。如果需要,您可以标记新属性以供审核。

您可以使用上述技术,如果 Attribute table 不存在,只需动态添加值即可。

当您不知道属性值且值多种多样时

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

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

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

编写代码以根据您的 Attribute table 验证这些值。如果它是单个或 multi-value...

则在那里有一个指标

AttributeMap 字段中这样存储:

{
    "Color": "Green", 
    "Size": "Medium", 
    "Categories": ["Sports", "Leisure"]
}

请注意类别是 multi-attribute。在您的 Attribute table 中,您应该有一个 IsMulti bool not null 字段,这将使您知道如何查询它。