Postgres 查询 jsonb 以根据另一个 name:value 对的值提取一个 name:value 对的值

Postgres query jsonb to extract value of one name:value pair based on value of a different name:value pair

我有一个使用 benthos 创建的 postgres table。dev/Golang 并且无法更改它的创建方式。 此 table 将 json 数据作为字符串插入到列中。 一个单独的 benthos yaml 将使用 postgres 查询它。 对于 table 中的 select 语句,其目的是找到具有“系统”给定名称的元素和 return 相应“值”的值。 (不是系统的值,称为“值”的元素的值) 所有响应都需要在同一行。 这是一个模型 专栏名称:Suigeneris

name Suigeneris
baz [{"system":"https://alpha.com/externalid","use":"home","value":"JJO5H0001"},{"system":"http://gee.org/berlin/uni/Suigeneris-num","use":"usual","value":"2122206077"}]

select 的期望输出是

name Suigeneris Sui-alpha Sui-berlin
baz [{"system":"https://alpha.com/externalid","use":"home","value":"JJO5H0001"},{"system":"http://gee.org/berlin/uni/Suigeneris-num","use":"usual","value":"2122206077"}] JJO5H0001 2122206077

我已经尝试了两种方法,并且正在使用此查询来获取有关使用 postgres select 所需数据的建议。我尝试在 postgres 中通过计算 {} 的位置然后使用它来分隔来执行此操作,但这会造成难以阅读且容易搞乱长查询。
示例:

select substring (Suigeneris from (position ( '{' IN Suigeneris )) for (position ( '}' IN Suigeneris ))-(position ( '{' IN Suigeneris ))) 
from table  

我只试过第一个位置。
我也尝试使用 regex_match 并且这有效但确实要求名称的顺序始终相同(例如“系统是第一个”)。看起来这是真的但不确定如果源系统决定会发生什么切换它。

SELECT (regexp_match(identifier,'("system":"http:\/\/gee.org\/berlin\/uni\/Suigeneris-num.*)(?=})')) as npi
FROM table 

但是,问题是我必须将该查询放入 YAML 文件并获取 'unexpected scalar at node end' - 我尝试使用单引号 '"' 和双引号 """ 转义双引号。查看 Yaml 文档,我不理解解决方案。 postgres 查询将进入 yaml 文件。

再次注意,目的是读取一个 name:value 对并从该对象中的另一个 name:value 对中提取值。对于“system”:“https...alpha...”提取“value”的值。 两种解决方案都提取与一个值相关的整个序列,目的是在下一步中提取所需的值。但获得所描述的价值将是理想的。没有理由将整个对象保留在 {} 中。

一个选项可能是让正则表达式中的先行匹配在“berlin”文本之前选择第一个括号而不指定整个字符串。我未能找到一种方法将正则表达式定位在“柏林”并找到第一个 { 之前和之后的匹配项。这可能允许没有完整的 https 地址并可能解决 yaml 标量问题。

或者有更好的方法 使用“PostgreSQL 14.2

您可以使用 JSON path 查询:

select name, 
       "unique",
       jsonb_path_query_first("unique", '$[*] ? (@.system == "https://alpha.com/externalid").value') #>> '{}' as unique_alpha,
       jsonb_path_query_first("unique", '$[*] ? (@.system == "http://gee.org/berlin/uni/unique-num").value') #>> '{}' as unique_berlin
from the_table       

jsonb_path_query_first returns 一个 jsonb 值。不幸的是,没有直接从 jsonb 转换为文本。为此,使用 #>> '{}'

请注意,unique 是一个非常糟糕的列名选择,因为它是保留关键字。