如何过滤 json 列中嵌套值的行?
Posted
技术标签:
【中文标题】如何过滤 json 列中嵌套值的行?【英文标题】:How to filter rows on nested values in a json column? 【发布时间】:2015-02-16 14:10:59 【问题描述】:这是我的表格(简化,只有重要的列):
CREATE TABLE things (
id serial primary key
, name varchar
, blueprint json default ''
);
还有一些示例数据:
# select * from things;
id | name | blueprint
----+---------+-----------------------------------------------------------------------------
1 | Thing 1 |
2 | Thing 2 | "1":"name":"Iskapola","wight":"2"
3 | Thing 3 | "1":"name":"Azamund","weight":"3", "2":"name":"Iskapola","weight":"1"
4 | Thing 4 | "1":"name":"Ulamir","weight":"1", "2":"name":"Azamund","weight":"1"
我想选择在name
键下的任意位置具有'Azamund'
的行。
像这样的:
# select * from things where * ->> 'name' = 'Azamund';
id | blueprint
----+----------------------------------------------------------------------------
7 | "1":"name":"Azamund","weight":"3", "2":"name":"Iskapola","weight":"1"
8 | "1":"name":"Ulamir","weight":"1", "2":"name":"Azamund","weight":"1"
数据的嵌套与示例中的完全相同(只有一层)。 目前我们使用的是 PostgreSQL 9.3.5。
在 PostgreSQL 9.3 中可以吗?也许是 9.4?
【问题讨论】:
我不确定,但这可能会对您有所帮助***.com/questions/10560394/… 谢谢!我看到了那个问题...但是这里的区别-我不能写下name
列的关键路径...它可以在'1'
或'9'
键下。我仍然应该能够找到它。无论如何-谢谢。我已经添加了更多有问题的细节以突出显示它......(希望它很清楚)
所以只有一层嵌套?此外,实际的表定义总是很有帮助。数据类型可能是text
或json
或jsonb
? ...NOT NULL
?
@ErwinBrandstetter - 添加了有关表模式的更多信息。好吗?
我冒昧地整理了您的问题,因为我想我将来可能会提到它。我希望我抓住了要点?
【参考方案1】:
您的查询已结束。 json_each()
是关键功能。或jsonb_each()
为jsonb
。一些改进:
SELECT *
FROM things t
WHERE EXISTS (
SELECT FROM json_each(t.blueprint) b
WHERE b.value->>'name' ILIKE 'azamund'
);
老sqlfiddledb小提琴here
json_each()
已经将值作为json
数据类型返回。无需额外演员。
更好的是,在EXISTS
中使用LATERAL
引用。这比使用SELECT
列表中的集合返回函数取消嵌套要干净得多。相关:
使用ILIKE
(~~*
) 进行模式匹配。正则表达式匹配(~
、~*
)更强大,但也更昂贵。所以尽可能使用基本的LIKE
/ ILKE
。详情:
JSON 数组的替代方案
您已经看过我对 JSON 数组的相关回答:
How do I query using fields inside the new PostgreSQL JSON datatype?虽然对嵌套 JSON 对象的查询看起来很简单,但对数组有出色的索引支持:
Index for finding an element in a JSON array在 Postgres 12 中使用 SQL/JSON 可能会变得更简单/更高效...
【讨论】:
不错的改进!谢谢。【参考方案2】:我可以执行的最近查询(返回我需要的数据)是:
select *
from (select id, (json_each(blueprint)).value::json->>'name' as name
from stocks) as t
where t.name ~* 'azamund';
嗯...也许有更好的东西?
【讨论】:
以上是关于如何过滤 json 列中嵌套值的行?的主要内容,如果未能解决你的问题,请参考以下文章
Spark Sql 查询嵌套记录。我想先过滤嵌套的记录数组,然后爆炸(将它们展开成行)
如何使用映射或过滤器而不是列表推导过滤特定值的嵌套字典(pythonic 方式)?