【问题标题】:Postgres JSON equivalent to HSTORE subtract operatorPostgres JSON 等效于 HSTORE 减法运算符
【发布时间】:2014-06-01 12:29:31
【问题描述】:

Postgres 的 hstore 扩展有一个简洁的减法运算符:

hstore - text[]

hstore - hstore

在第一种情况下,它会删除在字符串数组中找到键的键/值对:在第二种情况下,它会从出现在第二个 hstore 中的第一个 hstore 中删除所有匹配的键/值对。

新的jsonb 数据类型似乎不存在此运算符。有没有简单的方法来执行这些任务?

【问题讨论】:

    标签: json postgresql hstore postgresql-json jsonb


    【解决方案1】:

    关键是 json_each() 函数,以及 PostgreSQL 中手动构建 json 值的能力。

    这是一个可以处理json - text[]的函数:

    CREATE OR REPLACE FUNCTION "json_object_delete_keys"(
      "json" json,
      VARIADIC "keys_to_delete" TEXT[]
    )
      RETURNS json
      LANGUAGE sql
      IMMUTABLE
      STRICT
    AS $function$
    SELECT COALESCE(
      (SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
         FROM json_each("json")
        WHERE "key" <> ALL ("keys_to_delete")),
      '{}'
    )::json
    $function$;
    

    要处理json - json 的情况,您只需更改WHERE 子句:

        WHERE "json"->>"key" <> ("remove"->>"key")),
    

    【讨论】:

    • 谢谢。我想出了一个 plpython 版本,但这看起来要快 4 个数量级!
    • 虽然,json - json 要求目标和移除对象中的键/值对必须相同。
    • @MatthewSchinckel 你是对的,json - json 的情况很特殊。我的第一个想法是在两个 json_each() 集合上使用 sql EXCEPT,但 "json"-&gt;&gt;"key" &lt;&gt; ("remove"-&gt;&gt;"key") 更好。
    【解决方案2】:

    已接受的答案很好,但对于 json - json 的情况,还可以通过检查 null 来改进:

    WHERE NOT null_as_value_cmp((this_j->>"key"), (that_j->>"key"))
    

    没有NULL 检查你得到{} 而不是{"a":1}

    # select json_subtract('{"a":1, "b":2}'::json, '{"b":2}'::json);
     json_subtract
    ---------------
     {}
    (1 row)
    

    null_as_value_cmp 是这样的,并绕过JsNull 被表示为数据库NULL

    CREATE OR REPLACE FUNCTION null_as_value_cmp(
        a text,
        b text
    )
      RETURNS boolean
      LANGUAGE sql
      IMMUTABLE
      CALLED ON NULL INPUT
    AS $function$
        SELECT CASE
            WHEN a IS NULL AND b IS NULL THEN
                TRUE
            WHEN (a IS NULL AND b IS NOT NULL) THEN
                FALSE
            WHEN (a IS NOT NULL AND b IS NULL) THEN
                FALSE
            WHEN a = b THEN
                TRUE
            ELSE
                FALSE
        END;
    $function$;
    

    [我没有足够的声望来评论;不确定这里的 SO 协议。]

    【讨论】:

    • 恐怕json - json 永远不会是理想的,因为json 没有相等运算符(我们能做的最好的就是检查它们的表示是否相等)——如果 OP(或任何对此感兴趣的人)都可以使用 use 9.4+,我强烈推荐 jsonb 类型,它具有相等运算符;像(this_j-&gt;"key")::jsonb &lt;&gt; (that_j-&gt;"key")::jsonb 这样的东西可以完成这项工作
    • @pozs 很好,我在表示(在本例中为文本)相等与正确的 json 比较时遇到了一堆麻烦。我已经在上面更新了。 [我们很想使用 9.4 jsonb,但必须等待 RDS 支持。]
    猜你喜欢
    • 2012-08-11
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 2020-08-24
    • 1970-01-01
    • 2010-12-19
    相关资源
    最近更新 更多