我正在使用PostgreSQL 9.6,我有一个名为"ItemDbModel"的表,其中有两列如下所示:
No integer,
Content jsonb
假设我放了很多记录,例如:
"No": 2, {"obj":"x","Item": {"Name": "BigDog", "Model": "NamedHusky", "Spec":"red dog"}}
"No": 4, {"obj":"x","Item": {"Name": "MidDog", "Model": "NamedPeppy", "Spec":"no hair"}}
"No": 5, {"obj":"x","Item": {"Name": "BigCat", "Model": "TomCat", "Spec":"blue color"}}
如何查询表中的以下信息:
- "Content.Item.Name"包含"Dog">和"Content.Item.Spec"包含"red"的记录。
- "Content.Item.Name"包含"Dog">或"Content.Item.Spec"包含"red"的记录。
- "Content.Item"中的任何 json 字段包含"dog"的记录。
并按"Content.Item.Name.length"排序?
谢谢!
您应该熟悉 JSON 函数和运算符。
-- #1
select *
from example
where content->'Item'->>'Name' ilike '%dog%'
and content->'Item'->>'Spec' ilike '%red%'
-- #2
select *
from example
where content->'Item'->>'Name' ilike '%dog%'
or content->'Item'->>'Spec' ilike '%red%'
-- #3
select distinct on(no) t.*
from example t,
lateral jsonb_each_text(content->'Item')
where value ilike '%dog%';
-- and
select *
from example t
order by length(content->'Item'->>'Name');
Postgres 12引入了实现SQL/JSON路径语言的新功能。使用该jsonpath
的替代查询可能如下所示:
-- #1
select *
from example
where jsonb_path_exists(
content,
'$ ? ($.Item.Name like_regex "dog" flag "i" && $.Item.Spec like_regex "red" flag "i")');
-- #2
select *
from example
where jsonb_path_exists(
content,
'$ ? ($.Item.Name like_regex "dog" flag "i" || $.Item.Spec like_regex "red" flag "i")');
-- #3
select *
from example
where jsonb_path_exists(
content,
'$.Item.* ? (@ like_regex "dog" flag "i")');
前两个查询与前两个查询基本相似,->
语法可能看起来比jsonpath
查询更简单、更令人愉快。应特别注意第三个查询,它使用通配符,因此无需使用昂贵的函数jsonb_each_text ()
,并且应该明显更快。
阅读文档:
- SQL/JSON 路径语言
- jsonpath 类型