【问题标题】:Query for element of array in JSON column查询 JSON 列中的数组元素
【发布时间】:2013-11-03 06:57:15
【问题描述】:

最近升级到使用 PostgreSQL 9.3.1 以利用 JSON 功能。在我的表中,我有一个 json 类型的列,其结构如下:

{
   "id": "123",
   "name": "foo",
   "emails":[
      {
        "id": "123",
        "address": "somethinghere"
      },
      {
        "id": "456",
        "address": "soemthing"
      }
   ]
} 

这只是用于问题目的的虚拟数据。

是否可以根据 id 查询 emails 数组中的特定项目?
差不多:“return email where id=123)”?

【问题讨论】:

    标签: sql json postgresql postgresql-9.3 lateral


    【解决方案1】:

    是的,这是可能的:

    SELECT *
    FROM   tbl t, json_array_elements(t.json_col->'emails') AS elem
    WHERE  elem->>'id' = 123;
    

    tbl 是您的表名,json_col 是 JSON 列的名称。

    此相关答案中的更多详细信息:

    有关此相关答案最后一段中隐含的CROSS JOIN LATERAL 的更多信息:

    支持这种查询的索引:

    【讨论】:

    • 这是迄今为止我看到的此类问题的最佳答案。
    • @ErwinBrandstetter 很抱歉,您能帮我解决这个问题吗:stackoverflow.com/q/49532773(提前致谢!)
    【解决方案2】:

    使用 Postgres 9.4+ 中的 JSONB 列,您可以使用包含运算符 @> 来查询数组中的元素:

    SELECT * FROM jsontest WHERE data @> '{ "emails": [{ "id": "123" }] }';
    

    更多详情请见Query for array elements inside JSON type

    这是一个工作示例:

    CREATE TABLE jsontest(data JSONB NOT NULL);
    INSERT INTO jsontest VALUES (
      '{
         "name": "foo",
         "id": "123",
         "emails": 
         [
           {
             "address": "somethinghere",
             "id": "123"
           },
           {
             "address": "soemthing",
             "id": "456"
           }
         ]
      }'
    );
    SELECT * FROM jsontest WHERE data @> '{ "emails": [{ "id": "123" }] }';
    
    data
    ----
    {"id": "123", "name": "foo", "emails": [{"id": "123", "address": "somethinghere"}, {"id": "456", "address": "soemthing"}]}
    

    (1 行)

    【讨论】:

    • 如何通过 id 123 删除地址?
    • delete FROM jsontest WHERE data @> '{ "emails": [{ "id": "123" }] }';
    【解决方案3】:

    偶然看到这个帖子,发现可以这样直接查询表:

    SELECT *
    FROM   table_name, json_array_elements(json_column) AS data
    WHERE  data->>'id' = 123;
    

    省略这部分:

    json_array_elements(t.json_col->'emails')
    

    【讨论】:

    • 这是超级超级有用的,我一直在努力使用 CTE 来尝试让它发挥作用,这很好地解决了我的需求。谢谢!
    【解决方案4】:

    你可以这么简单:

    SELECT * FROM table WHERE emails->>'id' = '123';
    

    您似乎将 id 存储为字符串,如果它是一个整数,您可以这样做:

    SELECT *  from table WHERE cast(emails->>'id' as integer ) = 123  ;
    

    或者你可以得到所有 id > 10 的行

    SELECT *  from table WHERE cast(emails->>'id' as integer ) > 10  ;
    

    【讨论】:

    • 我已经在 Postgres 9.4.4 上尝试过,但它不起作用:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    相关资源
    最近更新 更多