PostgreSQL用json数组中的模式反向LIKE

时间:2018-09-22 21:18:42

标签: json postgresql

此问题与PostgreSQL Reverse LIKE

有关

我有一个表a,其中包含一个json列a.matchersa.matchers是一组对象,每个对象都有属性pattern 给定一个inputString,我想获得所有其中至少matchers[].pattern个匹配inputString LIKE '%{pattern}%'

的行

所以基本上(作为伪查询):

SELECT * 
FROM a 
WHERE 
    'inputStringABC' LIKE ANY('%' || json_array_elements(a.matchers)->>'pattern' || '%') 

这可能吗?

p.s .: PostgreSQL版本为9.6.3

编辑:更广泛的现状描述:

表a:

           Column            |            Type             |                   Modifiers                   | Storage  | Stats target | Description
------------------------------+-----------------------------+-----------------------------------------------+----------+--------------+-------------
 uuid                         | uuid                        | not null default uuid_generate_v4()           | plain    |              |
 matchers                     | json                        |                                               | extended |              |

列匹配器中的JSON结构:

[
    {
        pattern: string;
    }
]

用例示例:

我有一个字符串“有些树看起来比其他树好”,并在表a中跟随以下行:

  • uuid: "123...", matchers: [{ pattern: "trees" }]
  • uuid: "987...", matchers: [{ pattern: "bees" }, { pattern: "plants" }]

"123..."出现在trees中时,查询应返回包含uuid "Some trees look nicer than others"的行

编辑2:

最后的查询对我有用,这要感谢s-man

SELECT DISTINCT                                                  
    uuid,
    pattern
FROM (
    SELECT 
        *, 
        jsonb_array_elements(a.matchers)->>'pattern' as pattern  
    FROM a
) s
WHERE 
    'Some trees look nicer than others' LIKE '%' || pattern || '%'   

1 个答案:

答案 0 :(得分:1)

表格

id   matchers
1    [{"abc": 1, "pattern": "ABC"}, {"pattern": "ABAB"}, {"cde": "FOO", "pattern": "AABB"}]
2    [{"pattern": "AB"}, {"cde": "BAR", "pattern": "CDE"}]
3    [{"abc": 2, "pattern": "CD"}, {"pattern": "FG"}] 

查询

SELECT DISTINCT                                                  -- C
    id,
    matchers
FROM (
    SELECT 
        *, 
        jsonb_array_elements(a.matchers)->>'pattern' as pattern  -- A
    FROM a
) s
WHERE 
    pattern LIKE '%AB%'                                          -- B

A:jsonb_array_elements将json数组扩展为每个数组元素一行。 ->>运算符将每个数组元素包含的pattern属性的值作为文本给出。

B:使用LIKE运算符过滤文本值

C:因为表已扩展,所以我们不得不再次缩小表,因为我们只希望通过子查询在每行中保存原始列。

结果

id   matchers
1    [{"abc": 1, "pattern": "ABC"}, {"pattern": "ABAB"}, {"cde": "FOO", "pattern": "AABB"}]
2    [{"pattern": "AB"}, {"cde": "BAR", "pattern": "CDE"}]

demo: db<>fiddle


如果您的列的类型为json而不是jsonb,则必须使用json_array_elements


编辑:在使问题更加清楚之后,我们发现该模式的用例是相反的。因此,可以通过将WHERE子句更改为以下内容来实现预期的结果:

'long input string including pattern' LIKE '%' || pattern || '%'

Further reading