34

我正在使用 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"}}

如何查询表:

  1. 记录“Content.Item.Name”包含“Dog”并且“Content.Item.Spec”包含“red”。
  2. “Content.Item.Name”包含“Dog”“Content.Item.Spec”包含“red”的记录。
  3. 记录“Content.Item”中的任何json 字段包含“dog”。

并按“Content.Item.Name.length”排序?

谢谢!

4

1 回答 1

55

您应该熟悉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 ()并且应该明显更快。

阅读文档:

于 2017-02-09T08:07:19.173 回答