如何从 Postgres 中的 jsonb 类型中仅选择特定键的值

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

我有一个

jsonb
列,其中的数据如下。

[
   {"key": "unit_type", "value": "Tablet", "display_name": "Unit Type"},
   {"key": "pack_type", "value": "Packet", "display_name": "Pack Type"},
   {"key": "units_in_pack", "value": "60", "display_name": "Units in Pack"},
   {"key": "item_unit", "value": "", "display_name": "Item unit"},
   {"key": "item_size", "value": "1", "display_name": "Item Size"}, 
   {"key": "details", "value": "", "display_name": "Details"},
   {"key": "slug", "value": "otc7087", "display_name": "Slug"}
]

我想从数组中获取

value
字段,该数组有一个名为
key
slug
,这样当我对表进行选择查询时,我可以从列中获取这个特定值。对于上面的行,当我执行
select name, slug, price from table
时,我应该得到
med1, otc7087, 100
作为输出。我无法为这个东西建立查询。我可以获得所有键或所有值,但如何在同一个选择查询中选择特定的键?

或者简单地说,如何从表格中选择

slugs
?这会回答。

postgresql jsonb
3个回答
7
投票

我相信你的 json 更加结构化, 试试 jsonb_to_recordset

例如:

select * from json_to_recordset('[
   {"key": "unit_type", "value": "Tablet", "display_name": "Unit Type"},
   {"key": "pack_type", "value": "Packet", "display_name": "Pack Type"},
   {"key": "units_in_pack", "value": "60", "display_name": "Units in Pack"},
   {"key": "item_unit", "value": "", "display_name": "Item unit"},
   {"key": "item_size", "value": "1", "display_name": "Item Size"}, 
   {"key": "details", "value": "", "display_name": "Details"},
   {"key": "slug", "value": "otc7087", "display_name": "Slug"}
]') as x(key int, value text, display_name text);

它将把 jsonb 转换为以键、值、display_name 作为列的表,然后您可以对其进行任何类型查询,它也适用于提取键,而 @Craig Ringer 建议您无法将其转换为像表之类的东西并触发复杂的选择查询(例如 not in 、 != 、范围查询 、ilike )将非常困难,并且性能可能会较差。


2
投票

您似乎想要搜索 json 数组的所有元素,以查找具有给定键的特定值的对象,然后返回另一个键的值(如果匹配)。

这样的事情就可以解决问题:

WITH my_table(jsonblob) AS (VALUES('[
   {"key": "unit_type", "value": "Tablet", "display_name": "Unit Type"},
   {"key": "pack_type", "value": "Packet", "display_name": "Pack Type"},
   {"key": "units_in_pack", "value": "60", "display_name": "Units in Pack"},
   {"key": "item_unit", "value": "", "display_name": "Item unit"},
   {"key": "item_size", "value": "1", "display_name": "Item Size"}, 
   {"key": "details", "value": "", "display_name": "Details"},
   {"key": "slug", "value": "otc7087", "display_name": "Slug"}
]'::jsonb))
SELECT elem ->> 'value'
FROM my_table
CROSS JOIN LATERAL jsonb_array_elements(jsonblob) elem
WHERE (elem ->> 'key') = 'slug';

即从表中选择,将数组解压为连接,通过查找具有值

key
的 json 键
slug
来过滤连接表中所需的对象,并在
value 中返回 json 键 
select
 的值
发现条款。

如果您想要来自同一个 json 对象的多个不同值,则需要多个连接,每个所需值一个连接。

这是一种非常丑陋的存储可变键/值格式数据的方式。我建议存储如下:

{"unit_type": {"value": "Tablet", "display_name": "Unit Type"}, ...}

您可以在其中实际查找密钥。


0
投票

对于今年提出这个问题的其他人来说,在 v12 的 Postgres 中添加了一个名为“jsonb_path_query”的函数,这使得这个问题变得更容易。我认为以下是所需要的:

select jsonb_path_query(<column-with-json>, '$ ? (@.key == "slug")')->>'value' from <table>
© www.soinside.com 2019 - 2024. All rights reserved.