在 PostgreSQL 中搜索 jsonb 数组

Posted

技术标签:

【中文标题】在 PostgreSQL 中搜索 jsonb 数组【英文标题】:Searching jsonb array in PostgreSQL 【发布时间】:2015-08-15 07:18:06 【问题描述】:

我正在尝试在 PostgreSQL 9.4 中搜索 JSONB 对象。我的问题类似于this thread。

但是我的数据结构略有不同,这导致了我的问题。我的数据结构是这样的:

[
    "id":1, "msg":"testing"
    "id":2, "msg":"tested"
    "id":3, "msg":"nothing"
]

我想通过 msg(RegEx、LIKE、= 等)在该数组中搜索匹配的对象。更具体地说,我希望表中 JSONB 字段具有与我的请求匹配的“msg”对象的所有行。

下面显示了一个类似于我的结构:

SELECT * FROM 
    (SELECT 
        '["id":1,"msg":"testing","id":2,"msg":"tested","id":3,"msg":"nothing"]'::jsonb as data) 
    as jsonbexample;

这表明尝试实现上述链接的答案,但不起作用(返回 0 行):

SELECT * FROM 
    (SELECT 
        '["id":1,"msg":"testing","id":2,"msg":"tested","id":3,"msg":"nothing"]'::jsonb as data) 
    as jsonbexample 
WHERE 
    (data #>> 'msg') LIKE '%est%';

谁能解释如何通过 JSONB 数组进行搜索?在上面的示例中,我想在表中查找其“数据”JSONB 字段包含“msg”匹配某些对象的任何行(例如,LIKE '%est%')。


更新

这段代码创建了一个新类型(以后需要):

CREATE TYPE AlertLine AS (id INTEGER, msg TEXT);

然后您可以使用它来使用 JSONB_POPULATE_RECORDSET 撕开列:

SELECT * FROM 
    JSONB_POPULATE_RECORDSET(
        null::AlertLine, 
        (SELECT '["id":1,"msg":"testing",
                  "id":2,"msg":"tested",
                  "id":3,"msg":"nothing"]'::jsonb 
         as data
        )
    ) as jsonbex;

输出:

 id |   msg   
----+---------
  1 | testing
  2 | tested
  3 | nothing

并加入约束:

SELECT * FROM 
    JSONB_POPULATE_RECORDSET(
        null::AlertLine, 
        (SELECT '["id":1,"msg":"testing",
                  "id":2,"msg":"tested",
                  "id":3,"msg":"nothing"]'::jsonb 
         as data)
        ) as jsonbex 
WHERE 
    msg LIKE '%est%';

输出:

id |   msg   
---+---------
 1 | testing
 2 | tested

所以剩下的部分问题是如何把它作为一个子句放在另一个查询中。

那么,如果上面代码的输出=x,我会怎么问:

SELECT * FROM mytable WHERE x > (0 rows);

【问题讨论】:

【参考方案1】:

你可以使用exists:

SELECT * FROM 
    (SELECT 
        '["id":1,"msg":"testing","id":2,"msg":"tested","id":3,"msg":"nothing"]'::jsonb as data) 
    as jsonbexample 
WHERE 
    EXISTS (SELECT 1 FROM jsonb_array_elements(data) as j(data) WHERE (data#>> 'msg') LIKE '%est%');

如下评论中提到的查询表:

SELECT * FROM atable 
WHERE EXISTS (SELECT 1 FROM jsonb_array_elements(columnx) as j(data) WHERE (data#>> 'msg') LIKE '%est%');

【讨论】:

非常感谢您!它确实非常有用并且确实有效。但是,我无法根据我的目的来调整它(如我原来的问题)。如果我需要,比如说,SELECT * FROM atable WHERE ,我将如何使用上面的代码? @browner87 我已经更新了答案。如果需要进一步解释,请发表评论。 @RadekPostołowicz 哦,谢谢!我有一个我无法解决的问题,这个问题和答案让它变得如此简单!也谢谢布朗纳。

以上是关于在 PostgreSQL 中搜索 jsonb 数组的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql:搜索jsonb对象数组时如何使用动态值?

PostgreSQL jsonb-通过数组元素搜索字符串

如何在 Postgresql 中对 JSONB 数组中的值求和?

在 postgresql、选项数组或对象中插入 jsonb 数据,有效方式

如何在 Postgresql 中实现对复杂嵌套 JSONB 的全文搜索

PostgreSQL 查询 JSONB 字段中的对象数组