【问题标题】:How to query a json column for empty objects?如何查询空对象的 json 列?
【发布时间】:2014-08-09 03:55:40
【问题描述】:

查找某个 json 列包含空对象 {} 的所有行。这对于 JSON 数组是可能的,或者如果我正在寻找对象中的特定键。但我只想知道对象是否为空。似乎找不到可以执行此操作的操作员。

 dev=# \d test
     Table "public.test"
  Column | Type | Modifiers
 --------+------+-----------
  foo    | json |

 dev=# select * from test;
    foo
 ---------
  {"a":1}
  {"b":1}
  {}
 (3 rows)

 dev=# select * from test where foo != '{}';
 ERROR:  operator does not exist: json <> unknown
 LINE 1: select * from test where foo != '{}';
                                      ^
 HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
 dev=# select * from test where foo != to_json('{}'::text);
 ERROR:  operator does not exist: json <> json
 LINE 1: select * from test where foo != to_json('{}'::text);
                                      ^
 HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
 dwv=# select * from test where foo != '{}'::json;
 ERROR:  operator does not exist: json <> json
 LINE 1: select * from test where foo != '{}'::json;
                                      ^
 HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

【问题讨论】:

    标签: json postgresql types jsonb


    【解决方案1】:

    对于数据类型 json 整体而言,没有相等(或不等)运算符,因为相等很难建立。在 Postgres 9.4 或更高版本中考虑jsonb,这是可能的。有关 dba.SE(最后一章)的相关答案中的更多详细信息:

    SELECT DISTINCT json_column ...... GROUP BY json_column 因相同原因失败(没有相等运算符)。

    将表达式的两边都转换为text 允许=&lt;&gt; 运算符,但这通常不可靠,因为相同 JSON 值有许多可能的文本表示。在 Postgres 9.4 或更高版本中,改为转换为 jsonb。 (或使用jsonb 开头。)

    然而,对于这种特殊情况空对象)它工作得很好:

    select * from test where foo::text <> '{}'::text;
    

    【讨论】:

    • 可能很明显,但这也适用于空数组,只需将 {} 替换为 []
    • 如果您正在寻找嵌套结构,您可以使用以下结构:select * from test where foo-&gt;&gt;'property' = '[]'; 其中结构可能类似于:{ "property": [], "foo": "bar" }
    • 这在有很多行的情况下非常糟糕,每个foo都是一个大结构;每个都被强制发短信!
    • 当我使用这个时,我不想添加 '{}'::text。可以吗? (我也没有使用 foo::text)
    【解决方案2】:

    根据JSON Functions and Operators documentation,您可以使用双箭头函数(-&gt;&gt;)来获取json对象或数组字段作为文本。然后对字符串进行相等性检查。

    所以这对我有用:

    SELECT jsonb_col from my_table
    WHERE jsonb_col ->> 'key' = '{}';
    

    或者如果它嵌套超过一层,请使用路径函数 (#&gt;&gt;)

    SELECT jsonb_col from my_table
    WHERE jsonb_col #>> '{key, nestedKey}' = '{}';
    

    撰写本文时当前支持的版本:

    支持的版本:当前 (13) / 12 / 11 / 10 / 9.6

    【讨论】:

      【解决方案3】:

      你必须小心。将所有数据转换为不同的类型以便您可以比较它在大型数据库上会出现性能问题。

      如果您的数据具有一致的密钥,那么您可以查找密钥是否存在。例如,如果计划数据是 {} 或 {id: '1'}

      然后你可以寻找没有'id'的项目

      SELECT * FROM public."user"
      where NOT(plan ? 'id')
      

      【讨论】:

        【解决方案4】:

        空 JSON 数组 [] 也可能是相关的。

        那么这对[]{} 都有效:

        select * from test where length(foo::text) > 2 ;
        

        【讨论】:

          【解决方案5】:

          从 PostgreSQL 9.5 开始,这种类型的 JSON 数据查询是不可能的。另一方面,我同意它会非常有用并为此创建了一个请求:

          https://postgresql.uservoice.com/forums/21853-general/suggestions/12305481-check-if-json-is-empty

          请随意投票,希望它会被实施!

          【讨论】:

            【解决方案6】:

            在 9.3 中,可以计算每个对象中的对并过滤没有的对

            create table test (foo json);
            insert into test (foo) values
            ('{"a":1, "c":2}'), ('{"b":1}'), ('{}');
            
            select *
            from test
            where (select count(*) from json_each(foo) s) = 0;
             foo 
            -----
             {}
            

            或测试存在,对于大物体可能更快

            select *
            from test
            where not exists (select 1 from json_each(foo) s);
            

            无论格式如何,这两种技术都可以完美运行

            【讨论】:

            • 为什么在这些示例中调用 json_each 之后的 s?它有什么用途?
            • @Stratus3D 它是子查询的强制别名,在本例中是函数。
            • 这也适用于数组,将json_each替换为json_array_elements
            猜你喜欢
            • 1970-01-01
            • 2020-08-11
            • 1970-01-01
            • 2022-10-13
            • 1970-01-01
            • 2015-07-03
            • 1970-01-01
            • 1970-01-01
            • 2019-07-09
            相关资源
            最近更新 更多