我在字段hotel_data
中有这样的JSON数据:
{
"title":"foo",
"description":[
{
"locale":"pt",
"content":"pt text"
},
{
"locale":"fr",
"content":"fr text"
}
]
}
我只想选择description
个描述。可以使用Postgres,如何使用?
我正尝试使用fr
,但是它不起作用...
->>
注意:
我不想使用SELECT
hotel_data->'description'->>'locale' = 'fr' AS description
FROM hotel LIMIT 1;
...
例外的输出:SELECT *
答案 0 :(得分:1)
您可以使用横向联接和json_to_recordset
将json数组扩展为一组记录。然后,您可以对生成的记录中的列locale
进行过滤,最后将新的json对象重组为预期的结果:
select json_build_object('description', d.content) hotel_data_descr_fr
from
mytable,
json_to_recordset(hotel_data->'description') as d("locale" text, "content" text)
where d.locale = 'fr'
with mytable as (
select '{
"title":"foo",
"description":[
{
"locale":"pt",
"content":"pt text"
},
{
"locale":"fr",
"content":"fr text"
}
]
}'::json hotel_data
)
select json_build_object('description', d.content) hotel_data_descr_fr
from
mytable,
json_to_recordset(hotel_data->'description') as d("locale" text, "content" text)
where d.locale = 'fr'
| hotel_data_descr_fr | | :------------------------- | | {"description": "fr text"} |
答案 1 :(得分:1)
可以使用@>
运算符完成过滤,该运算符可以使用hotel_data
列上的GIN索引。通常,这比扩展阵列要快。
select ...
from hotel
where hotel_data @> '{"description": [{"locale":"fr"}] }';
这也可以扩展为包括更多属性:
select ...
from hotel
where hotel_data @> '{"description": [{"locale":"fr", "headline": "nice view'}] }';
但是您只能用它在键/值对上表示相等条件。无法使用LIKE
。如果要执行此操作,则必须扩展数组,并在WHERE子句中应用条件-请参见GMB的答案。
要提取该描述,我将使用标量子查询:
select (select jsonb_build_object('description', t.descr ->> 'content')
from jsonb_array_elements(h.hotel_data -> 'description') as t(descr)
where t.descr ->> 'locale' = 'fr'
limit 1)
from hotel h
where h.hotel_data @> '{"description": [{"locale":"fr"}] }';
这样一来,您无需扩展数组即可进行过滤,如果只有少数几家酒店符合该条件,我希望这样做会更快。但是它的缺点是您需要在子选择中的语言环境上重复条件。
如果您有多个法语描述,则限制1仅是一个安全网。如果您从未拥有过它,也不会受伤
使用Postgres 12,这更容易:
select jsonb_build_object(
'description',
jsonb_path_query_first(hotel_data, '$.description ? (@.locale == "fr")') -> 'content'
)
from hotel
where hotel_data @> '{"description": [{"locale":"fr"}] }'
以上所有假设hotel_data
是一个jsonb
列,如果不是(应该是),则需要对其进行强制转换:hotel_data::jsonb