查询 Postgres 9.3 JSON 以检查数组是否包含字符串?

Query Postgres 9.3 JSON to check if array contains a string?

我的 JSON 列中的一行看起来像这样:

{"general": {
        "somekey": "somevalue", 
        "tags": ["first_tag", "second_tag", "third_tag"]}}

我需要 return 包含特定标签的标签列表行(例如 "first_tag")。有没有办法在 PostgreSQL 9.3 中执行此操作?

假设 table 被称为 t 并且该列被称为 x:

SELECT *
FROM t
WHERE exists(
  SELECT 1
  FROM json_array_elements(x#>'{general,tags}')
  WHERE array_to_json(array[value])->>0='first_tag'
);

这不使用 jsonb 或其他更新的内容,因此它应该适用于 9.3。另见 sqlfiddle.

想法是使用json_array_elements 函数,它将json 数组转换为sql table。 table 有一个名为 value 的列,类型为 json

在这种情况下,我们在子查询中使用 json_array_elements 来遍历所有标签的列表。一个复杂的问题是 value(这里代表一个标签)是 json 类型,因此我们必须将其转换为文本。不幸的是,postgresql 没有直接执行此操作的函数,因此我们必须将其转换为单个元素数组,然后将该单个元素提取为文本。然后我们可以将该文本与我们要查找的标签(上例中的 first_tag)进行比较。这一列的结果并不重要,我们只关心它是否为空。

您可以使用:

CREATE OR REPLACE FUNCTION fn_json_array_contains(a_json json, a_e anyelement)
RETURNS BOOLEAN AS $BODY$
BEGIN
    RETURN to_json(a_e)::TEXT IN (SELECT value::TEXT FROM json_array_elements(a_json) e);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE
;

SELECT * FROM t WHERE fn_json_array_contains(x#>'{general,tags}', 'first_tag');