寻找基于jsonb

时间:2018-04-01 14:22:01

标签: postgresql jsonb entity-attribute-value

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

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

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

值将保存在attributes

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

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

我看到了几个选项:

1。商店格式如

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

其中value_idcustom value喜欢文字或id来自Values表。但我无法理解如何在此格式上构建索引,例如,如果Attribute 10integer

2。仅保留Attribute表(用于控制属性name)并存储数据,如:

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

。这种方法更适合索引

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

但我在翻译文本属性和控制唯一值时会遇到问题。另外,我无法在选项1中添加其他键:{"attribute_id":1, "value":5, "values": []}

使用唯一控件(对于唯一属性)存储额外字段以及有机会编制索引的最佳方法是什么。

1 个答案:

答案 0 :(得分:6)

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

我不建议使用单独的属性值表,就像我们在过去几年中所做的那样。将jsonb字段放在相应的表格中并将其命名为Attributes。向其添加GIN索引,以便您可以快速查询值。或者使用其中描述的其他技术。

阅读本文: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 not 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

假设您有一个名为Items的表格,并且您已添加AttributeSet

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

翻译时,这意味着它具有Color=Green属性和Size=Medium属性。 103112足以存储该内容,但有时可以说“#34;向我显示所有已定义任何尺寸的项目"”,#39} ;为什么要包括110。

你可以使这种闪电变得更加灵活。

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

将返回包含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"]
}

请注意,Categories是一个多属性。在您Attribute表格中,您应该有一个IsMulti bool not null字段,以便您了解如何查询该字段。