如何对 hstore/jsonb 列的键执行模式匹配查询?

How to perform a pattern matching query on the keys of a hstore/jsonb column?

我正在尝试对 Postgresql 数据库的 hstore 列执行模式匹配 table。

这是我尝试过的:

SELECT
  *
FROM
 products
WHERE
  'iphone8' LIKE ANY(AVALS(available_devices))

不过,ANY运算符好像只支持<<=<>

我也试过这个:

SELECT
  *
FROM
 products
WHERE
  ANY(AVALS(available_devices)) LIKE 'iphone8'

但随后会引发 SyntaxError。

那么,我可以使用 WHERE 子句进行查询吗?我在该子句中传递了一个参数,查询的结果是包含通知 hstore_column 中与给定参数?

例如: 对于行

id | hstore_column
1       { country: 'brazil' }
2       { city: 'amsterdam' }
3       { state: 'new york' }
4       { count: 10 }
5       { counter: 'Irelia' }

我想执行带有参数 'count'WHERE,我希望结果为:

id  |  hstore_column
1       { country: 'brazil' }
4       { count: 10 }
5       { counter: 'Irelia' }

您可以使用 jsonb_object_keys 将键变成一列。然后匹配密钥。

例如,这是我的测试数据。

select * from test;

 id |                    stuff                    
----+---------------------------------------------
  1 | {"country": "brazil"}
  2 | {"city": "amsterdam"}
  3 | {"count": 10}
  4 | {"pearl": "jam", "counting": "crows"}
  5 | {"count": "chocula", "count down": "final"}

然后我们可以使用jsonb_object_keys将每个键变成它自己的行。

select id, stuff, jsonb_object_keys(stuff) as key
from test;

 id |                    stuff                    |    key     
----+---------------------------------------------+------------
  1 | {"country": "brazil"}                       | country
  2 | {"city": "amsterdam"}                       | city
  3 | {"count": 10}                               | count
  4 | {"pearl": "jam", "counting": "crows"}       | pearl
  4 | {"pearl": "jam", "counting": "crows"}       | counting
  5 | {"count": "chocula", "count down": "final"} | count
  5 | {"count": "chocula", "count down": "final"} | count down

这可以在子 select 中使用以获得每个匹配的 key/value 对。

select id, stuff, key, stuff->key as value
from (
  select id, stuff, jsonb_object_keys(stuff) as key
  from test
) pairs
where key like 'count%';

 id |                    stuff                    |    key     |   value   
----+---------------------------------------------+------------+-----------
  1 | {"country": "brazil"}                       | country    | "brazil"
  3 | {"count": 10}                               | count      | 10
  4 | {"pearl": "jam", "counting": "crows"}       | counting   | "crows"
  5 | {"count": "chocula", "count down": "final"} | count      | "chocula"
  5 | {"count": "chocula", "count down": "final"} | count down | "final"

或者我们可以使用 distinct 来获取匹配的行。

select distinct id, stuff
from (
  select id, stuff, jsonb_object_keys(stuff) as key
  from test
) pairs
where key like 'count%';

 id |                    stuff                    
----+---------------------------------------------
  1 | {"country": "brazil"}
  3 | {"count": 10}
  4 | {"pearl": "jam", "counting": "crows"}
  5 | {"count": "chocula", "count down": "final"}

dbfiddle


注意:必须搜索键表示您的数据结构可能需要重新考虑。传统的 key/value table 可能效果更好。这些值仍然可以是 jsonb。设置多了一点,但查询更简单,索引也更容易。

create table attribute_group (
  id bigserial primary key
);

create table test (
  id bigserial primary key,
  attribute_group_id bigint
    references attribute_group(id) 
    on delete cascade
);

create table attributes (
  attribute_group_id bigint
    references attribute_group(id) not null,
  key text not null,
  value jsonb not null
);

select test.id, attrs.key, attrs.value
from test
join attributes attrs on attrs.attribute_group_id = test.attribute_group_id
where attrs.key like 'count%';

dbfiddle