在 PostgreSQL 中搜索 jsonb 数组

bro*_*r87 6 regex postgresql jsonb

我正在尝试在 PostgreSQL 9.4 中搜索 JSONB 对象。我的问题类似于这个线程

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

[
    {"id":1, "msg":"testing"}
    {"id":2, "msg":"tested"}
    {"id":3, "msg":"nothing"}
]
Run Code Online (Sandbox Code Playgroud)

我想通过 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;
Run Code Online (Sandbox Code Playgroud)

这显示了尝试实现上述链接的答案,但不起作用(返回 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%';
Run Code Online (Sandbox Code Playgroud)

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


更新

此代码创建了一个新类型(稍后需要):

CREATE TYPE AlertLine AS (id INTEGER, msg TEXT);
Run Code Online (Sandbox Code Playgroud)

然后你可以用它来撕开带有 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;
Run Code Online (Sandbox Code Playgroud)

输出:

 id |   msg   
----+---------
  1 | testing
  2 | tested
  3 | nothing
Run Code Online (Sandbox Code Playgroud)

并加入约束:

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%';
Run Code Online (Sandbox Code Playgroud)

输出:

id |   msg   
---+---------
 1 | testing
 2 | tested
Run Code Online (Sandbox Code Playgroud)

因此,仍然存在的问题部分是如何将其作为子句放入另一个查询中。

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

SELECT * FROM mytable WHERE x > (0 rows);
Run Code Online (Sandbox Code Playgroud)

Rad*_*icz 5

您可以使用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%');
Run Code Online (Sandbox Code Playgroud)

要查询下面评论中提到的表:

SELECT * FROM atable 
WHERE EXISTS (SELECT 1 FROM jsonb_array_elements(columnx) as j(data) WHERE (data#>> '{msg}') LIKE '%est%');
Run Code Online (Sandbox Code Playgroud)