当前位置: 首页 > 面试题库 >

展平来自JSONB字段的聚合键/值对?

隆钊
2023-03-14
问题内容

我在使用下表的Postgres 9.4中工作:

     Column      │         Type         │ Modifiers
─────────────────┼──────────────────────┼──────────────────────
 id              │ integer              │ not null default
 practice_id     │ character varying(6) │ not null
 date            │ date                 │ not null
 pct_id          │ character varying(3) │
 total_list_size │ double precision     │ not null
 star_pu         │ jsonb                │

我有以下查询:

SELECT date,
       AVG(total_list_size) AS total_list_size,
       json_object_agg(key, val) AS star_pu
FROM (SELECT date,
             SUM(total_list_size) AS total_list_size,
             key, SUM(value::numeric) val FROM frontend_practicelist p,
             jsonb_each_text(star_pu)
       GROUP BY date, key ) p
GROUP BY date
ORDER BY date;

它为我提供了带有JSON对象的结果star_pu

date            │ 2013-04-01
total_list_size │ 56025123.000000000000
star_pu         │ { "antidepressants_cost" : 180102416.8036909901975399, "antiepileptic_drugs_cost" : 296228344.171576079922216... }

相反,我想将JSON结果展平为一系列命名空间的键,因此结果如下所示:

date            │ 2013-04-01
total_list_size │ 56025123.000000000000
star_pu.antidepressants_cost        │ 180102416.8036909901975399
star_pu.antiepileptic_drugs_cost    │ 296228344.171576079922216 
...

这可能吗?


问题答案:

这种特殊情况

下面的函数基于表动态创建视图:

create or replace function create_totals_view(table_name text)
returns void language plpgsql as $$
declare
    s text;
begin
    execute format ($fmt$
        select string_agg(format('star_pu->>''%s'' "%s"', key, key), ',')
        from (
            select distinct key
            from %s, json_each(star_pu)
            order by 1
            ) s;
        $fmt$, '%s', '%s', table_name)
    into s;
    execute format('
        drop view if exists %s_view;
        create view %s_view as 
        select date, total_list_size, %s from %s', 
        table_name, table_name, s, table_name);
end $$;

首先,从查询中创建一个表。

create table totals as

    SELECT date,
           AVG(total_list_size) AS total_list_size,
           json_object_agg(key, val) AS star_pu
    FROM (SELECT date,
                 SUM(total_list_size) AS total_list_size,
                 key, SUM(value::numeric) val FROM frontend_practicelist p,
                 jsonb_each_text(star_pu)
           GROUP BY date, key ) p
    GROUP BY date
    ORDER BY date;

接下来,使用函数,该函数将创建一个以_viewpostfix 表命名的视图:

select create_totals_view('totals');

最后,查询视图:

select * from totals_view;

通用解决方案(适用于jsonb)

create or replace function create_jsonb_flat_view
    (table_name text, regular_columns text, json_column text)
    returns text language plpgsql as $$
declare
    cols text;
begin
    execute format ($ex$
        select string_agg(format('%2$s->>%%1$L "%%1$s"', key), ', ')
        from (
            select distinct key
            from %1$s, jsonb_each(%2$s)
            order by 1
            ) s;
        $ex$, table_name, json_column)
    into cols;
    execute format($ex$
        drop view if exists %1$s_view;
        create view %1$s_view as 
        select %2$s, %3$s from %1$s
        $ex$, table_name, regular_columns, cols);
    return cols;
end $$;

用法:

create table example (id int, name text, params jsonb);
insert into example values
(1, 'Anna', '{"height": 175, "weight": 55}'),
(2, 'Bob', '{"age": 22, "height": 188}'),
(3, 'Cindy', '{"age": 25, "weight": 48, "pretty": true}');

select create_jsonb_flat_view('example', 'id, name', 'params');

select * from example_view;

 id | name  | age | height | pretty | weight 
----+-------+-----+--------+--------+--------
  1 | Anna  |     | 175    |        | 55
  2 | Bob   | 22  | 188    |        | 
  3 | Cindy | 25  |        | true   | 48
(3 rows)


 类似资料:
  • 问题内容: 假设我有以下模型: 网站的用户可以将其图像贡献给多个比赛。然后其他用户可以投票赞成或反对。 一切正常,但现在我想显示一个页面,用户可以在该页面上查看对某个竞赛的所有贡献。图片应按其得分排序。因此,我尝试了以下方法: 我担心它不起作用,因为没有可在查询中使用的数据库字段。 问题答案: 哦,当然,我忘了Django中新的聚合支持及其功能。 因此查询可能如下所示:

  • 我有一些架构/模式问题。假设我有一个有两个类的域模型。我使用代码优先和存储库模式。(为了使示例更简单,我只使用字段,而不使用属性) 我还有PersonDto和PetDto类,唯一不同的是,PersonDto中的Pets字段是一个简单的List。我使用Automapper将模型类转换为dto。接下来通过REST Api将Dto发送给客户端。现在,如果在某个视图中,我需要为每个人显示其姓名、姓氏和宠物

  • 我想根据组字段G对文档进行分组。我使用弹性文档中描述的“字段聚合”策略按包含文档的最大分数对存储桶进行排序(在弹性文档中称为“字段折叠示例”),如下所示: 此查询还包括每个存储桶中的最高命中数。如果存储桶的最大分数不是唯一的,我想指定一个二阶列。从应用程序上下文中,我知道在存储桶中,所有文档共享相同的字段F值。因此,该字段应用作二阶列。 如何在Elastic中实现这一点?有没有办法使顶部命中子聚合

  • 我有一个由LiberOffice Draw 4.1.0.4创建的PDF表格。 表单包含文本字段、复选框和单选按钮 在我为字段设置值并使用PDFBox(2.0.21)展平表单后,无法显示字段值 我认为这可能是该字段注释的外观问题,但我不知道如何使其正确 测试PDF

  • 问题内容: 我想在字段上使用stats或extended_stats聚合,但是找不到完成此操作的任何示例(即,似乎只能将聚合与实际文档字段一起使用)。 是否有可能计算出“元数据”在ElasticSearch查询响应每个命中字段请求集合(例如,,,,等等)? 我假设答案是“否”,因为未对类似字段进行索引… 问题答案: 注意:就最新版本的Elasticsearch而言,原始答案现在已过时。使用Groo

  • 我在elasticsearch中有一个文档索引,每个文档有480个字段。我试图做的是搜索一个词(例如“Apple”),并获得所有其值与搜索词匹配的唯一字段名。所以如果我的文档是: 作为查询的结果,我希望得到如下所示的聚合: 由于每个文档都有480个字段,所以我更喜欢执行multi_match查询,而不是使用包含所有字段的筛选器: 这个查询在ElasticSearch中可能吗?