使用 postgres jsonb 类型和 pgcrypto 大火

Taking heavy fire with postgres jsonb types and pgcrypto

我有一个 postgres table 和一个 jsonb 列,目的是插入灵活的文档然后制作一些搜索

让我们从 table 和一些说明性数据开始:

create table my_table (id serial primary key, label text, document jsonb);

insert into my_table (label, document) values ('white', '{"name": "john", "lastname": "doe", "eyes": "brown", "birth": "07/08/1979 19:12:55", "pet": "dinosour", "wife": "872", "cat": "no"}');
insert into my_table (label, document) values ('lemon', '{"name": "jane", "lastname": "doe", "birth": "07/08/1978 19:12:55", "cat": "yes"}');
insert into my_table (label, document) values ('white', '{"name": "peter", "eyes": "blue", "birth": "07/08/1980 19:12:55", "pet": "worm", "dog": "yes"}');
insert into my_table (label, document) values ('cyanide', '{"name": "peter", "lastname": "doe", "doormat": "yes"}');

当数据开始流动时,正在创建一些索引(这就是列类型为jsonb的原因),例如:

create index on my_table (((document->>'name')::text)) WHERE (document->>'name') is not null and label = 'white';
create index on my_table (((document->>'lastname')::text)) WHERE (document->>'lastname') is not null and label = 'lemon';
create index on my_table (((document->>'doormat')::text)) WHERE (document->>'doormat') is not null and label = 'cyanide';

此时一切都按预期工作,我们能够以良好的性能执行不错的搜索,例如:

select * from my_table
where to_timestamp(document->>'birth', 'DD/MM/YYYY HH24:MI:SS')  
    between to_timestamp('07/08/1979 00:00:00', 'DD/MM/YYYY HH24:MI:SS') 
    and     to_timestamp('07/08/1979 23:59:59', 'DD/MM/YYYY HH24:MI:SS');

select * from my_table where document->>'cat' = 'yes' or document->>'eyes' = 'brown';

问题 是现在我们需要加密数据库中的信息,就像我通常使用 pgcrypto 所做的那样,但我找不到加密 jsonb 类型 没有失去所有的索引能力或字段的搜索能力将我推回到一个非常原始的状态。

我们发现关于 jsonb 类型的 pgcrypto 的信息太少,例如: and the pgcrypto documentation don't say anything about jsonb types https://www.postgresql.org/docs/10/static/pgcrypto.html

有没有办法让我们做类似 pgp_sym_decrypt(jsonb, 'secret') 的事情?或者我们可以在不丢失至少字段搜索功能的情况下加密数据的另一种机制? (我们可以牺牲索引)

提前致谢,

谢谢@Jasen,你的评论让我开始思考......,正如我所说,我们可以牺牲索引,然后将加密数据存储为 bytea 并将其转换回 jsonb 应该没有问题需要,使用类似的东西:

... where (pgp_sym_decrypt(document, 'secret')::jsonb)->>'name' = 'peter';