暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL处理文档数据

作者:昆明畅博科技有限公司  李晓光(黑哥)  2020年6月3日

1  大多数人的选择

     采用json处理文档数据,PostgreSQL有两种 JSON 数据类型:json和jsonb,它们接受完全相同的值集合作为输入,两种类型的区别就是效率:
     json数据类型存储输入文本的精准拷贝,处理函数必须在每次执行时必须重新解析该数据。
     jsonb数据被存储在一种分解好的二进制格式中,它在输入时要稍慢一些,因为需要做附加的转换。但是 jsonb在处理时要快很多,因为不需要解析。
     如果是读取密集型,请选择使用jsonb类型,如果是写入密集型,请选择json类型。如果你为这就完了,那么下面的就是But.
     虽然PostgreSQL的json和jsonb类型确实很好很强大、扩展性非常强,但是json带来的问题就是数据的字段、字段数量、字段类型可能不完全统一,虽然可以通过文档规范json,但是只要是人就不可避免的出现错误,因此在实际使用中PostgreSQL内部存储时建议使用自定义类型。
     自定义类型和json之间可以互相转换、添加/修改/删除类型字段是并不会对已有数据造成影响、可以强制指定json各字段的数据类型、数据库读写自定义类型比json方便和高效。

2  使用自定义类型处理

    drop table if exists documents;
    drop type if exists ctdocument;

    create type ctdocument as (
      标题 text,
      作者 text,
      内容 text
    );

    create table documents(
        objectid bigserial not null,                           --编号
        doc ctdocument not null,                               --文档,注意类型为ctdocument
        constraint pk_documents_objectid primary key(objectid)
    );
    这里定义了一个基本的文档类型,然后创建了一个表存储数据,现在先写入一部份数据。
      insert into documents(docvalues(('标题1','作者1','内容1')::ctdocument);
      insert into documents(docvalues(('标题2','作者2','内容2')::ctdocument);
      insert into documents(docvalues(('标题3','作者3','内容3')::ctdocument);
      insert into documents(docvalues(('标题4','作者4','内容4')::ctdocument);
      insert into documents(docvalues(('标题5','作者5','内容5')::ctdocument);
      --读取类型中的字段
      select objectid,(doc)."标题",doc from documents;
      --转换为json
      select objectid,row_to_json(doc),doc from documents;
      2.1修改类型字段名
        alter type ctdocument rename attribute "标题" to title;
        --这时读取类型中的字段要改用新的名字
        select objectid,(doc).title,doc from documents;
        --转换为json5.select objectid,row_to_json(doc),doc from documents;
        2.2添加类型字段
          alter type ctdocument add attribute "发布日期"  timestamptz;
          alter type ctdocument add attribute "阅读数"  integer;
          --列出类型定义
          \dS+ ctdocument;
          --重新插入一条数据
          insert into documents(docvalues(('标题6','作者6','内容6',now(),1)::ctdocument);
          --读取类型中的字段
          select objectid,(doc).title,doc from documents;
          --转换为json10.select objectid,row_to_json(doc),doc from documents;
          2.3删除类型字段
            alter type ctdocument drop attribute if exists "发布日期";
            --列出类型定义
            \dSctdocument;
            --读取类型中的字段
            select objectid,(doc).title,doc from documents;
            --转换为json
            select objectid,row_to_json(doc),doc from documents;
            2.4修改类型字段类型
            修改类型字段的类型语法为
              alter type ctdocument add attribute "发布日期"  timestamptz;
              --注意,"发布日期"在2.3中已经被删除,然后重新添加的,此时的自定义类型顺序已经和2.2中不一样了,所以建议不要删除自定义类型的字段
              insert into documents(doc) values(('标题7','作者7','内容7',1,now())::ctdocument);
              alter type ctdocument alter attribute "发布日期" set data type date;
              但是已经使用的自定义类型不支持修改自定义类型中的字段类型,修改会报一个异常:
                ERROR:  cannot alter type "ctdocument" because column "documents.doc" uses it
                     意思是自定义类型“"”ctdocument”已经在表“documents”中的“doc”字段中使用了,折中的方法是删除自定义类型中的字段然后再重新创建(表参看2.2、2.3节)。需要注意的是删除并重新创建后该字段的值为null,需要重新设置。

                3  自定义类型和json相互转换

                     这里有两个函数需要注意json_populate_record、json_populate_recordset,如果只转一行数据用jsonb_populate_record,如果要转多数据用jsonb_populate_recordset。
                3.1json_populate_record函数
                  select * from json_populate_record(null::ctdocument,null);
                  select * from json_populate_record(null::ctdocument,(select row_to_json(doc) from documents where objectid=6));
                  select (json_populate_record(null::ctdocument,row_to_json(doc)))::ctdocument as doc from documents;
                  3.2json_populate_recordset函数
                    --null
                    select * from json_populate_recordset
                    (null::ctdocument,null);
                    --将表中的数据转换为json数组
                    select array_to_json(array_agg(row_to_json(doc) order by objectid)) from documents;
                    --将json数组转换为记录集显示
                    select * from json_populate_recordset
                    (null::ctdocument,(select array_to_json(array_agg(row_to_json(doc) order by objectid)) from documents));
                    --转换为json然后再转换回来
                    select (t1) from json_populate_recordset
                    (null::ctdocument,(select array_to_json(array_agg(row_to_json(doc) order by objectid)) from documents)) as t1;

                    4  结束语

                         IT人员要避免循规蹈矩,对充分发挥独立的思想和创意,当然需要充分理解和掌握相关知识。世界上没有绝对的最好和最差,再好的东西也可能用起来发挥不出效能,不好的东西也能用起来得心应手,这里主要是想强调和鼓励发挥人的因素,能很好的满足业务的需求就是最好的。

                    I Love PG

                    关于我们

                    中国开源软件推进联盟PostgreSQL分会(简称:中国PG分会)于2017年成立,由国内多家PostgreSQL生态企业所共同发起,业务上接受工信部中国电子信息产业发展研究院指导。中国PG分会是一个非盈利行业协会组织。我们致力于在中国构建PostgreSQL产业生态,推动PostgreSQL产学研用发展。



                    欢迎投稿

                    做你的舞台,show出自己的才华 。

                    投稿邮箱:partner@postgresqlchina.com

                                                   

                                                     ——愿能安放你不羁的灵魂


                    技术文章精彩回顾




                    PostgreSQL学习的九层宝塔
                    PostgreSQL职业发展与学习攻略
                    搞懂PostgreSQL数据库透明数据加密之加密算法介绍
                    一文读懂PostgreSQL-12分区表
                    一文搞懂PostgreSQL物化视图
                    PostgreSQL源码学习之:RegularLock
                    Postgresql源码学习之词法和语法分析
                    2019,年度数据库舍 PostgreSQL 其谁?
                    Postgres是最好的开源软件
                    PostgreSQL是世界上最好的数据库
                    从Oracle迁移到PostgreSQL的十大理由
                    从“非主流”到“潮流”,开源早已值得拥有
                    PostgreSQL国际专家系列直播:请选出你最想听的分享主题

                    PG活动精彩回顾




                    创建PG全球生态!PostgresConf.CN2019大会盛大召开
                    首站起航!2019“让PG‘象’前行”上海站成功举行
                    走进蓉城丨2019“让PG‘象’前行”成都站成功举行
                    中国PG象牙塔计划发布,首批合作高校授牌仪式在天津举行
                    群英论道聚北京,共话PostgreSQL
                    相聚巴厘岛| PG Conf.Asia 2019  DAY0、DAY1简报
                    相知巴厘岛| PG Conf.Asia 2019 DAY2简报
                    独家|硅谷Postgres大会简报
                    PostgreSQL线上沙龙第一期精彩回顾
                    PostgreSQL线上沙龙第二期精彩回顾
                    PostgreSQL线上沙龙第三期精彩回顾
                    PostgreSQL线上沙龙第四期精彩回顾
                    PostgreSQL线上沙龙第五期精彩回顾
                    PostgreSQL线上沙龙第六期精彩回顾

                    PG培训认证精彩回顾




                    中国首批PGCA认证考试圆满结束,203位考生成功获得认证!
                    中国第二批PGCA认证考试圆满结束,115位考生喜获认证!
                    重要通知:三方共建,中国PostgreSQL认证权威升级!
                    近500人参与!首次PGCE中级、第三批次PGCA初级认证考试落幕!
                    通知:PostgreSQL技术能力电子证书上线!
                    2020年首批 | 中国PostgreSQL初级认证考试圆满结束

                    最后修改时间:2020-06-04 09:22:16
                    文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论