使用 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"
我正在尝试使用 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"