查询 JSON 数组元素中的键

问题描述 投票:0回答:1

我假设我的 PostgreSQL 表中有一个

jsonb
header_format
(结果是类型
json[]
,真的)。

列值如下所示:

{"{\"label\":\"SUPPLIER\",\"name\":\"supplier_name\",\"value\":\"VNS LTD\",\"show\":true,\"showPrint\":true,\"map\":\"\",\"input_type\":\"text\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"PRODUCT NAME\",\"name\":\"product_name\",\"value\":\"\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"INVOICE / DC #\",\"name\":\"invoice_no\",\"value\":\"cs/12/1222\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"INVOICE / DC DATE\",\"name\":\"invoice_date\",\"value\":\"2022-06-02\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"DATE_EXT\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"INVOICE QTY\",\"name\":\"invoice_qty\",\"value\":260,\"show\":true,\"showPrint\":true,\"input_type\":\"number\",\"map\":\"invoiceQty\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"No Need to Map\"}","{\"label\":\"IR #\",\"name\":\"ir\",\"value\":\"FY-23-09-1\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"GRN NO\",\"name\":\"grn_no\",\"value\":\"5032344565\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"GRN DATE\",\"name\":\"grn_date\",\"value\":\"2022-06-02\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"LAST_GR_DATE_EXT\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"R/M CODE\",\"name\":\"rmcode\",\"value\":\"CR11803C00MAN\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"EDS /Q /P #\",\"name\":\"eds\",\"value\":\"DE / EDS / 454\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"eds\",\"mapFrom\":\"product\",\"default\":true,\"note\":\"\"}","{\"label\":\"DATE\",\"name\":\"date\",\"value\":\"2022-09-13\",\"show\":true,\"showPrint\":true,\"input_type\":\"date\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"R/M\",\"name\":\"rm\",\"value\":\"DC01+LC-MA-RL\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"rm\",\"mapFrom\":\"product\",\"default\":true,\"note\":\"\"}","{\"label\":\"RECEIVED QTY\",\"name\":\"received_qty\",\"value\":260,\"show\":true,\"showPrint\":true,\"input_type\":\"number\",\"map\":\"invoiceQty\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"No Need to Map\"}","{\"label\":\"SHELF LIFE\",\"name\":\"shelf_life\",\"value\":\"20.11.2022\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"Shelf Life\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"No Need to Map\"}","{\"label\":\"MATERIAL TEXT\",\"name\":\"material_text\",\"value\":\"CP7B-DC01,1.18 x 31.5\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"MATTEXT\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}"}

我正在

header_format
列中插入格式:

[{
label:'1',
value:'abc',
other...
},
{
label:'2',
value:'aab',
other...
}]

我想要一个与数组数据类型中的

"{label:'supplier'}"
匹配的行列表。

我尝试了以下方法:

方法一:

Database.rawQuery('select * from qasformones  where header_format @> "{label:supplier}"')

方法二:

Database.rawQuery('select * from qasformones  where header_format @> "[{label:supplier}]"')

我收到以下错误:

列“{label:supplier}”不存在

从 qasformones 中选择 *,其中 header_format @>“{label:supplier}” - 列“{show:true}”不存在

如何进行此查询?

sql postgresql database-design knex.js jsonb
1个回答
2
投票

此查询适用于您当前的表设计,包含 JSON 值数组 (

json[]
):

SELECT *
FROM   qasformones q
WHERE  EXISTS (
   SELECT FROM unnest(q.header_format) js
   WHERE  js->>'label' = 'SUPPLIER'   -- match case!
   );

但是

json[]
通常不是您想要的。存储效率低下,而且该查询成本高昂且扩展性不佳。考虑将列转换为
jsonb
包含数组或对象。

通往理智的快速之路

ALTER TABLE
是最快的方法 - 如果您有能力独占锁定表。参见:

但它不允许在

USING
子句中使用子查询表达式。因此,将功能包装在一个快速的临时函数中。 (在会话结束时自动删除。)

CREATE FUNCTION pg_temp.jsb_transform (json[])
  RETURNS jsonb
  LANGUAGE sql AS
$func$
SELECT jsonb_agg(js) FROM unnest($1) js;
$func$;

ALTER TABLE qasformones
   ALTER COLUMN header_format TYPE jsonb USING pg_temp.jsb_transform(header_format);

那么我建议:

VACUUM FULL ANALYZE qasformones;

并创建索引:

CREATE INDEX qasformones_header_format_gin_idx ON qasformones USING gin (header_format jsonb_path_ops);

关于:

现在您的查询可以是:

SELECT *
FROM   qasformones q
WHERE  header_format @> '[{"label":"SUPPLIER"}]';

或者,在 Postgres 12+ 中使用 SQL/JSON 路径表达式

SELECT *
FROM   qasformones q
WHERE  header_format @? '$ ? (@.label == "SUPPLIER")';

小提琴

常规表格列?

您的内容看起来非常有规律。然而,使用

jsonb_populate_recordset()
将键分解为专用的常规表列可能会更有效,请参阅:

这将导致当前

json[]
中的 N 个数组元素有 N 行。可能是一对多的设计。相关:

© www.soinside.com 2019 - 2024. All rights reserved.