用于在 JSON 数组中查找元素的索引

2023-12-02

我有一个看起来像这样的表:

CREATE TABLE tracks (id SERIAL, artists JSON);

INSERT INTO tracks (id, artists) 
  VALUES (1, '[{"name": "blink-182"}]');

INSERT INTO tracks (id, artists) 
  VALUES (2, '[{"name": "The Dirty Heads"}, {"name": "Louis Richards"}]');

还有其他几个与此问题无关的专栏。将它们存储为 JSON 是有原因的。

我想做的是查找具有特定的曲目艺术家姓名(完全符合)。

我正在使用这个查询:

SELECT * FROM tracks 
  WHERE 'ARTIST NAME' IN
    (SELECT value->>'name' FROM json_array_elements(artists))

例如

SELECT * FROM tracks
  WHERE 'The Dirty Heads' IN 
    (SELECT value->>'name' FROM json_array_elements(artists))

然而,这会进行全表扫描,而且速度不是很快。我尝试使用函数创建 GIN 索引names_as_array(artists),并使用'ARTIST NAME' = ANY names_as_array(artists),但是没有使用索引,并且查询实际上明显慢了。


jsonb在 Postgres 9.4+ 中

二进制 JSON 数据类型jsonb很大程度上改进了索引选项。您现在可以在以下位置拥有 GIN 索引:jsonb直接数组:

CREATE TABLE tracks (id serial, artists jsonb);  -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);

不需要函数来转换数组。这将支持查询:

SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';

@>jsonb“包含”运算符,可以使用GIN索引。 (不是为了json, only jsonb!)

Or您使用更专业的非默认 GIN 操作符类jsonb_path_ops对于索引:

CREATE INDEX tracks_artists_gin_idx ON tracks
USING  gin (artists jsonb_path_ops);  -- !

同样的查询。

现在jsonb_path_ops只支持@>操作员。但它通常更小、更快。还有更多索引选项,手册中的详细信息.


If专栏artists仅保存示例中显示的名称,仅存储名称会更有效values作为 JSON 文本原语和多余的key可以是列名称。

请注意 JSON 对象和原始类型之间的区别:

  • 在 PostgreSQL 中使用 json 数组中的索引
CREATE TABLE tracks (id serial, artistnames jsonb);
INSERT INTO tracks  VALUES (2, '["The Dirty Heads", "Louis Richards"]');

CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames);

Query:

SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';

?不适用于对象values, just keys and 数组元素.

Or:

CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING  gin (artistnames jsonb_path_ops);

Query:

SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;

如果名称高度重复,效率会更高。

json在 Postgres 9.3+ 中

这应该与IMMUTABLE function:

CREATE OR REPLACE FUNCTION json2arr(_j json, _key text)
  RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)';

创建这个功能性的index:

CREATE INDEX tracks_artists_gin_idx ON tracks
USING  gin (json2arr(artists, 'name'));

并使用一个query像这样。中的表达式为WHERE子句必须与索引中的子句匹配:

SELECT * FROM tracks
WHERE  '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));

根据评论中的反馈进行了更新。我们需要使用数组运算符支持GIN索引。
The “包含于”运算符<@在这种情况下。

关于函数波动性的注释

你可以声明你的函数IMMUTABLE即使json_array_elements()不是 不是。
Most JSON以前的功能只是STABLE, not IMMUTABLE. 黑客名单上有一场讨论要改变这一点。大多数是IMMUTABLE现在。检查:

SELECT p.proname, p.provolatile
FROM   pg_proc p
JOIN   pg_namespace n ON n.oid = p.pronamespace
WHERE  n.nspname = 'pg_catalog'
AND    p.proname ~~* '%json%';

功能索引仅适用于IMMUTABLE功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于在 JSON 数组中查找元素的索引 的相关文章

随机推荐

  • 在 Chrome Devtools 中看不到本地存储键值对

    我有一个 json 文件 用于存储使用 javascript 在我的页面上显示的数据 此 json 文件及其键值对在 Chrome 的开发工具中不可见或不可访问 该组件管理 json 文件 Takes a filename and a JS
  • 使用 Jquery Mobile 进行 XML 解析

    我有以下格式的 XML 我想提取 标题 和 子菜单 标签 并从中创建一个菜单栏结构 如下图所示
  • 如何处理龙卷风中的帕尔斯指令?

    我是龙卷风框架的新手 当我打开网址时torchado web RequestHandler 需要处理 parms 的字典 请看下面的代码 class MainHandler tornado web RequestHandler def ge
  • 使用 log4j2 的多个线程的不同日志文件

    我正在运行一个 Java 应用程序 其中调用多个线程 每个线程都有一些唯一的名称 现在我想为每个日志文件创建多个日志文件 日志文件的名称应该与线程名称相同 使用 log4j2 可以吗 请帮我写log4j2配置文件 先感谢您 我同意 Rout
  • 用户提交的 HTML 带来的安全风险

    我正在使用 contentEditable div 它允许用户编辑正文 HTML 然后使用 AJAX 请求将其直接发布到网站 当然 我还要对其进行一些安全检查 最明显的是通过搜索确保没有提交任何脚本标签
  • 如何修复 Eclipse/Android 安装?图形 XML 编辑器中的 PNG 加载问题

    很长一段时间以来 我的带有 Android 插件的 Eclipse 环境都运行顺利 在软件更新过程中应用的更新的某个地方 它崩溃了 开始发生的第一个问题是在运行布局文件的 Android 插件图形编辑器时丢失 按钮 Form Widget
  • 如何访问 R 中的嵌套 SQL 表?

    来自 R Studio 的ODBC 数据库文档我可以看到一个如何将 SQL 表读入 R 数据框的简单示例 data lt dbReadTable con flights 让我粘贴一个图形BGBUreftable 我正在尝试读取 R 数据帧
  • 将ScheduledJob注册为系统帐户(无需传入凭据)

    我相信对于Register ScheduledTask你可以指定 User System 或者做类似的事情 principal New ScheduledTaskPrincipal UserId SYSTEM LogonType Servi
  • 通过递增/递减最后找到的值向前/向后填充 na?

    给定以下 pandas 数据框 可以找到它的副本here 如何在单独的列中填充 na 并递增 递减 nr 行 直到下一个信号值和前向 后向信号值 信号值只有 1 1 或 np na Values Signal 0 1420 49 1 142
  • 使用 Javascript forEach 和 indexOf 在 JSON 中搜索多个过滤器

    我有 JSON 格式的数据 需要在其中执行搜索 有不同的可用标签 当我单击它们时 它会在 JSON 中搜索并返回具有这些标签的项目 为此 我使用了 js 函数 它第一次工作正常 但是当我在函数中推送第二个过滤器时 它返回错误的数据 可用的过
  • RFC_READ_TABLE 传递“选项”和“字段”参数 (c#)

    需要帮助 我正在尝试使用 RFC READ TABLE 从 SAP 获取销售数据 但不知道如何将 OPTIONS 和 FIELDS 参数传递给 SAP 这是我的应用程序的示例代码 连接正常 执行后出现异常 DATA BUFFER EXCEE
  • 有没有办法防止opencv矩阵除法的舍入

    我有一个整数矩阵 我想对其进行整数除法 但opencv总是对结果进行四舍五入 我知道我可以手动划分每个元素 但我想知道是否有更好的方法 Mat c Mat
  • TCP Keepalive 是确定断开链接的唯一机制吗?

    我最近遇到了一个问题 TCP 服务器和客户端之间的中间链路出现故障 如果主服务器宕机 客户端需要连接到辅助服务器 当主服务器被关闭时 例如 通过在终端上执行 C TCP 关闭序列会通过 并且客户端成功检测到断开的链接并尝试辅助服务器 然而
  • Tomcat 7 上部署时出现 Omnifaces 异常

    我正在尝试将 Omnifaces 2 1 添加到 Web 应用程序以使用 FullAjaxExceptionHandler 以及 Omnifaces 2 1 中可能的其他功能 我已阅读并关注了 BallusC 的以下帖子 但仍然陷入困境 如
  • 格式良好的 XML?标记名称和属性名称中的 XML 引用

    我一直在尝试确认我对 XML 规范的阅读 我的解释是 标签名称和属性名称中不允许使用预定义实体和数字字符引用 例如 XML 1 0 规范不允许这样做
  • MS Edge:IntersectionObserver。对你起作用吗?

    在任何人在这里付出太多努力之前 我已经有了一个令人讨厌的解决方法 我只是想知道是否有人可以使用它 Edge 版本 15 现已发布 并支持交叉观察器 用于延迟加载 我已经实现了它 它在所有支持它的浏览器中都可以正常工作 Chrome 和 Op
  • Rails 随机记录生成器

    我问自己是否有一个gem或一种方法可以用随机数据生成大量记录 对模型有效 目标是使用数据库中的大量数据来测试我的应用程序 我在网上没有找到任何内容 但我没有使用正确的关键字 你知道类似的事情吗 您可以使用Faker宝石 并且 以下是创建 1
  • 如何将查询语句记录到Neo4j服务器,可能吗?

    我想将整个查询语句记录到 Neo4j 服务器 但是 在搜索 SO 和文档之后我没有成功 我发现这个问题 Neo4j 服务器上记录的剩余查询 但是更改这些配置设置并没有达到我所希望的效果 我在 Golang 工作并使用Go CQ库与 Neo4
  • 如何让 Twitter Bootstrap Accordion 保持一组开放?

    我正在尝试使用 Twitter 引导程序使用手风琴和折叠插件来模拟 Outlook 栏 到目前为止 我已经实现了折叠和手风琴工作 但它目前允许折叠所有部分 我想限制它 以便始终显示一个且仅一个 这是我正在研究的一个 http jsfiddl
  • 用于在 JSON 数组中查找元素的索引

    我有一个看起来像这样的表 CREATE TABLE tracks id SERIAL artists JSON INSERT INTO tracks id artists VALUES 1 name blink 182 INSERT INT