当前位置: 首页 > 知识库问答 >
问题:

查询包含JSON对象数组的jsonb列

王辉
2023-03-14

我使用PostgreSQL 9.5和Rails 5。我想查询下面显示的包含JSON对象数组的jsonb列,以返回包含{“kind”:“person”}的所有JSON数组元素,并执行计数
我使用的SQL显示在json数据下面。运行查询只返回一个空数组。

我尝试了这里和这里建议的查询。

这就是我的jsonb数据的样子:

   '[
        {"kind":"person", "filter_term":"56","selected_attr":"customer"},
        {"kind":"email", "filter_term":"marketer","selected_attr":"job_title"}
      ]'

我希望其中一个sql查询返回:

                             data
----------------------------------------------------------------------
 '{"kind":"person", "filter_term":"56","selected_attr":"customer"}'
(1 row)

和另一个返回数组的查询,以便我可以在我的应用程序中调用count并循环使用它来创建表单:

 data
----------------------------------------------------------------------
 '[{"kind":"person", "filter_term":"56","selected_attr":"customer"}]'
 (1 row)

我尝试了以下SQL查询:

 "SELECT * FROM \"segments\" WHERE (payload @> '[{\"kind\":\"person\"}]')"

我还尝试了这个查询:

  "SELECT payload FROM segments WHERE payload @> '[{\"kind\":\"person\"}]'::jsonb;"

这是第三个查询:

 "SELECT * FROM segments s WHERE s.payload->'\"#{a}\"' @> '[{\"kind\":\"person\"}]';"

模型:

class Segment < ApplicationRecord
 store_accessor :payload,:kind, :filter_term, :selected_model_name, :selected_attr, :limit, :selected_operator
end

迁移:

create_table "segments", force: :cascade do |t|

  t.jsonb    "payload",    default: "[]", null: false
  t.index ["payload"], name: "index_segments_on_payload", using: :gin

end

共有1个答案

戚哲
2023-03-14

假设此表定义:

CREATE TABLE segments (segments_id serial PRIMARY KEY, payload jsonb);

JSON值如下:

INSERT INTO segments (payload)
VALUES ('[
            {
                "kind": "person",
                "limit": "1",
                "filter_term": "56",
                "selected_attr": "customer",
                "selected_operator": "less_than"
            },
            {
                "kind": "email",
                "filter_term": "marketer",
                "selected_attr": "job_title",
                "selected_operator": "equals"
            }
        ]'
   );
  • 您希望返回包含键/值对"type":"man"(不是嵌套的JSON对象{"class":"man"})的JSON数组元素-并计算数组元素以及表行(每行可能有多个匹配的数组元素)。

要获取列中包含符合条件的jsonb值的行数,请执行以下操作:

SELECT count(*)
FROM   segments s
WHERE  s.payload @> '[{"kind":"person"}]';

要获取所有符合条件的JSON数组元素(即JSON对象本身),请加上元素总数(可能同时大于上述计数):

SELECT j.*
FROM   segments s
JOIN   LATERAL jsonb_array_elements(s.payload) j(elem) ON j.elem @> '{"kind":"person"}'
WHERE  s.payload @> '[{"kind":"person"}]';

返回值:

elem
------------------------------------------------------------
{"kind": "person", "limit": "1", "filter_term": "56", ... }

要一次获得全部:

SELECT j.*, count(*) OVER () AS ct_elem, s.ct_rows
FROM  (
   SELECT payload, count(*) OVER () AS ct_rows
   FROM   segments
   WHERE  payload @> '[{"kind":"person"}]'
   ) s
JOIN   LATERAL jsonb_array_elements(s.payload) j(elem) ON j.elem @> '{"kind":"person"}';

返回(对于包含更多条目的表):

elem                      | ct_elem | ct_rows
--------------------------+---------+---------
{"kind": "person",  ... } | 4       | 3
{"kind": "person",  ... } | 4       | 3
...

但我想你真的想要这个:

SELECT a.*
     , sum(ct_elem_row) OVER () AS ct_elem_total
     , count(*)         OVER () AS ct_rows
FROM   segments s
JOIN   LATERAL (
   SELECT json_agg(j.elem) AS filtered_payload, count(*) AS ct_elem_row
   FROM   jsonb_array_elements(s.payload) j(elem)
   WHERE  j.elem @> '{"kind":"person"}'
   ) a ON ct_elem_row > 0
WHERE  s.payload @> '[{"kind":"person"}]';

返回(对于包含更多条目的表):

filtered_payload                                     | ct_elem_row | ct_elem_total | ct_rows
-----------------------------------------------------+-------------+---------------+---------
[{"kind": "person", ... }]                           | 1           | 4             | 3
[{"kind": "person", ... }]                           | 1           | 4             | 3
[{"kind": "person", ... }, {"kind": "person", ... }] | 2           | 4             | 3

这将标识匹配的行,然后选择匹配的数组元素并仅使用这些元素为每行构建一个数组。加号计数。

为了获得最佳性能,您需要一个jsonb\u path\u ops

CREATE INDEX segments_path_ops_gin_idx ON segments 
USING  gin (payload jsonb_path_ops);

(但更通用的索引来服务于更多不同的查询可能是更好的选择。)

相关:

>

  • 用于在JSON数组中查找元素的索引

    查询JSON类型内的数组元素

    在应用限制之前获取结果计数的最佳方法

    术语

    我们正在处理一个包含JSON数组的JSON对象,保存为Postgresjsonb数据类型——简称“JSON数组”,但不是“JSON数组”。

  •  类似资料:
    • 问题内容: 我使用 PostgreSQL 9.5 和Rails5。我想查询下面显示的包含JSON对象数组的列,以返回包含并执行计数的所有JSON数组元素。我使用 的 SQL 显示在json数据下方。运行查询只会返回一个空数组。 这是我的数据: 我想要其中一个sql查询返回: 和另一个查询以返回数组,以便我可以在应用程序中对其调用count,还可以遍历它以创建表单: 我试过这个SQL查询: 我也试过

    • 问题内容: 我的JSON数据如下所示: 给定文本“ foo”,我想返回所有具有此子字符串的元组。但是我不知道如何编写相同的查询。 我遵循了这个相关的答案,但不知道该怎么做。 这是我现在正在工作的内容: 我不想传递整个文本,而是传递并获得与该文本匹配的结果。 问题答案: 您的解决方案可以进一步简化: 或更简单一点,因为在此示例中,您实际上根本不需要行类型(): dbfiddle 在这里 但这 不是

    • 我希望在每个数组中获取多个对象,但我的代码显示了单个对象的操作。下面是我的PHP代码,我如何添加另一个循环来获取多个对象 这是显示单个物体的结果

    • 问题内容: Postgres具有此JSON数据类型,我想知道如何查询JSON数组中的数据?我正在使用Postgres 9.3.1 我已插入具有以下两个字段名称的PUBLISHER表:字符串和数据:json 我想查询并列出类型为“小说”的作者。在这种情况下,应该是“ James”和“ Tom”作为输出。 这种查询的内容: 问题答案: 您可以使用该函数从数组生成: 有了它,您可以将其用作子查询,这样就

    • 问题内容: 好的,所以我试图从我用来学习Java的书中进行练习。这是我到目前为止的代码: 以下是确切措词的练习: 修改类Calculator.java,以将所有数字按钮保留在声明为10个元素的数组中,如下所示: 替换从10开始的行 带有创建按钮并将其存储在此数组中的循环。 好的,所以我尝试使用声明数组,但这给了我错误: 这行有多个标记- 按钮无法解析为类型- 按钮无法解析为类型 相反,我尝试了这个

    • 背景:我们使用书面记录来记录我们不断变化的模型的历史。现在我想查询一个属于某个客户的项目。PaperTrail可选择存储对象更改,我需要查询此字段以了解何时使用此ID创建了某些内容或更改为此ID。 我的表看起来简化如下: 如何查询从或更改为ID 5的元素(因此上面的所有行)?我试过: 这让我: