You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何筛选JSONB数组中包含指定值的行

PostgreSQL JSONB数组主题筛选方案

问题背景

表c的topics列是JSONB类型,存储的是包含id和name字段的对象数组,需要筛选出包含指定主题名称的行,支持单个主题或多个主题的筛选需求。

单个主题筛选(例如"Finance")

方法1:使用@>包含运算符

@>运算符要求左侧JSONB包含右侧的结构,由于topics是对象数组,需要构造一个包含目标主题对象的数组作为匹配条件:

SELECT id, topics
FROM c
WHERE topics @> '[{"name": "Finance"}]'::jsonb;

该语句会匹配所有topics数组中至少存在一个name为"Finance"的对象的行。

方法2:展开数组后筛选

通过jsonb_array_elements将数组展开为行,再通过EXISTS子查询判断是否存在目标主题:

SELECT id, topics
FROM c
WHERE EXISTS (
    SELECT 1
    FROM jsonb_array_elements(c.topics) AS t
    WHERE t->>'name' = 'Finance'
);

此方法更适合需要添加复杂筛选条件的场景。

多个主题筛选

场景1:包含所有指定主题(例如同时包含"Finance"和"Politics")

方法1:多条件@>组合

通过AND连接多个@>条件,确保数组中同时存在所有指定主题:

SELECT id, topics
FROM c
WHERE topics @> '[{"name": "Finance"}]'::jsonb
  AND topics @> '[{"name": "Politics"}]'::jsonb;

方法2:展开数组后分组计数

展开数组后筛选目标主题,通过分组计数确认所有主题都存在:

SELECT id, topics
FROM c
CROSS JOIN jsonb_array_elements(c.topics) AS t
WHERE t->>'name' IN ('Finance', 'Politics')
GROUP BY id, topics
HAVING COUNT(DISTINCT t->>'name') = 2; -- 数字对应指定主题的数量

场景2:包含任意一个指定主题(例如包含"Finance"或"Politics")

方法1:多条件@>+OR组合

通过OR连接多个@>条件,匹配存在任意一个目标主题的行:

SELECT id, topics
FROM c
WHERE topics @> '[{"name": "Finance"}]'::jsonb
   OR topics @> '[{"name": "Politics"}]'::jsonb;

方法2:展开数组后IN筛选

通过EXISTS子查询结合IN语句,匹配存在任意目标主题的行:

SELECT id, topics
FROM c
WHERE EXISTS (
    SELECT 1
    FROM jsonb_array_elements(c.topics) AS t
    WHERE t->>'name' IN ('Finance', 'Politics')
);

错误写法说明

你之前尝试的topics @> '{"name": ["Finance"]}'无效,原因是右侧JSON结构与左侧不匹配:左侧topics是对象数组,而右侧是一个单键对象(键为name,值为数组),两者结构完全不同,因此无法匹配。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 01:20:24