使用 jsonb 的 postgres 上的 EAV

EAV on postgres using jsonb

我正在尝试使用 Attribute->Value 表来实现 EAV 模式,但不同于存储在 jsonb 中的标准方式值,如 {"attrId":[values]}。它有助于简化搜索请求,例如:

SELECT * FROM products p WHERE p.attributes @> "{1:[2]} AND p.attributes @> "{1:[4]}"

现在我想知道这是否是一个好方法,什么是计算可用变体数量的有效方法,例如:

-p1- {"width":[1]} -p2- {"width":[2],"height":[3]} -p3- {"width":[1]}

输出会

width: 1(计数 2); 2(计数 1)

height: 3(计数 1)

当 select width 2

width: 1(计数 0); 2(计数 1)

height: 3(计数 1)

“扁平优于嵌套”——python

的禅宗

我认为您最好使用简单的 key/value 对,并且在极少数情况下您有一个复杂的值,然后将其制成一个列表。但是我没有看到那个用例。

这是一个可以回答您问题的示例。可以对其进行修改以使用您的结构,但让我们保持简单:

首先创建一个table并插入一些JSON:

# create table foo (a jsonb);
# insert into foo values ('{"a":"1", "b":"2"}');
# insert into foo values ('{"c":"3", "d":"4"}');
# insert into foo values ('{"e":"5", "a":"6"}');

记录如下:

# select * from foo;
          a
----------------------
 {"a": "1", "b": "2"}
 {"c": "3", "d": "4"}
 {"a": "6", "e": "5"}
(3 rows)

这是 https://www.postgresql.org/docs/9.6/static/functions-json.html

中 json_each_text() 函数的输出
# select jsonb_each_text(a) from foo;
 jsonb_each_text
-----------------
 (a,1)
 (b,2)
 (c,3)
 (d,4)
 (a,6)
 (e,5)
(6 rows)

现在我们需要将它放在 table 表达式中以便能够访问各个字段:

# with t1 as (select jsonb_each_text(a) as rec from foo) 
  select (rec).key, (rec).value from t1;

 key | value
-----+-------
 a   | 1
 b   | 2
 c   | 3
 d   | 4
 a   | 6
 e   | 5
(6 rows)

最后是使用 SUM 函数的分组。请注意数据库 2x 中的 a 密钥已正确求和。

# with t1 as (select jsonb_each_text(a) as rec from foo) 
  select (rec).key, sum((rec).value::int) from t1 group by (rec).key;

 key | sum
-----+-----
 c   |   3
 b   |   2
 a   |   7
 e   |   5
 d   |   4
(5 rows)

最后一点,(rec) 有括号,否则它会被错误地视为 table 并会导致此错误:

ERROR:  missing FROM-clause entry for table "rec"