You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PostgreSQL中如何对jsonb顶层键值对的值执行ILIKE查询?

实现PostgreSQL jsonb顶层值的ILIKE模糊查询

当然可以实现!针对你存储的这种键值全为字符串的jsonb列,要对所有顶层值做ILIKE模糊查询,我给你分享几种实用的方案:

1. 遍历所有顶层键值对匹配

如果你需要检查任意一个顶层值是否匹配模糊条件,可以用jsonb_each_text函数把jsonb列的顶层键值对展开,再通过JOIN关联筛选:

SELECT t.*
FROM your_table t
JOIN jsonb_each_text(t.jsonb_col) AS j(key, value)
  ON j.value ILIKE '%xxx%';

如果同一个jsonb列里有多个值匹配条件,上面的语句会重复返回原表的行。要是想避免重复,可以加上DISTINCT

SELECT DISTINCT t.*
FROM your_table t
JOIN jsonb_each_text(t.jsonb_col) AS j(key, value)
  ON j.value ILIKE '%xxx%';

2. 针对单个指定键的匹配

如果你只需要查询某个特定键的值,直接用->>操作符提取字符串值就行,这也是你最初思路的实现方式:

SELECT * 
FROM your_table 
WHERE jsonb_col->>'key1' ILIKE '%xxx%';

3. 性能优化:针对大数据量的索引方案

如果你的表数据量很大,上面的方法会触发全表扫描,效率较低。这里提供两种索引优化思路:

3.1 Trigram索引(适合模糊查询)

先安装pg_trgm扩展(PostgreSQL的 trigram 模糊匹配工具):

CREATE EXTENSION IF NOT EXISTS pg_trgm;

然后创建基于所有顶层值拼接文本的trigram索引:

CREATE INDEX idx_jsonb_all_values_trgm ON your_table
USING gin (
  array_to_string(
    array(SELECT value FROM jsonb_each_text(jsonb_col)),
    ' '
  ) gin_trgm_ops
);

查询时用同样的拼接逻辑来利用索引:

SELECT DISTINCT t.*
FROM your_table t
WHERE array_to_string(
        array(SELECT value FROM jsonb_each_text(t.jsonb_col)),
        ' '
      ) ILIKE '%xxx%';

3.2 全文索引(适合关键词匹配)

如果你的模糊查询更偏向关键词搜索,可以用全文索引:

CREATE INDEX idx_jsonb_all_values_tsv ON your_table
USING gin (
  to_tsvector(
    'english',
    array_to_string(
      array(SELECT value FROM jsonb_each_text(jsonb_col)),
      ' '
    )
  )
);

查询时用全文搜索语法(比如匹配包含xxx的关键词):

SELECT t.*
FROM your_table t
WHERE to_tsvector(
        'english',
        array_to_string(
          array(SELECT value FROM jsonb_each_text(t.jsonb_col)),
          ' '
        )
      ) @@ to_tsquery('english', 'xxx');

注意事项

  • 如果jsonb列可能存在NULL值,可以在查询里加上WHERE jsonb_col IS NOT NULL避免报错;
  • 索引会增加写入时的开销,需要根据你的读写比例权衡是否创建。

内容的提问来源于stack exchange,提问作者crowmagnumb

火山引擎 最新活动