检查PostgreSQL jsonb列是否包含特定字符串的快速方法

检查PostgreSQL jsonb列是否包含特定字符串的快速方法,postgresql,Postgresql,在过去的两天里,我读了很多关于jsonb、全文搜索、gin索引、trigram索引之类的内容,但我仍然找不到一个明确的答案,或者至少是一个足够好的答案,来说明如何快速搜索jsonb类型的行是否包含某个字符串作为值。由于它是一种搜索功能,因此其行为应该与ILIKE类似 我得到的是: Table,我们称之为app.Table_1,它包含很多列,其中一列是JSONB类型的,所以我们称之为column_JSONB 列_jsonb中的数据将始终是平坦的(没有嵌套对象等),但键可能会有所不同。列中具有模

在过去的两天里,我读了很多关于jsonb、全文搜索、gin索引、trigram索引之类的内容,但我仍然找不到一个明确的答案,或者至少是一个足够好的答案,来说明如何快速搜索jsonb类型的行是否包含某个字符串作为值。由于它是一种搜索功能,因此其行为应该与ILIKE类似

我得到的是:

  • Table,我们称之为app.Table_1,它包含很多列,其中一列是JSONB类型的,所以我们称之为column_JSONB

  • 列_jsonb中的数据将始终是平坦的(没有嵌套对象等),但键可能会有所不同。列中具有模糊值的数据示例如下所示:
    “{”“Key1”“:”“Value1”“Key2”“:”“Value2”“Key3”“:null”“Key4”“:”“Value4”“Key5”“:”“Value5”“}

  • 我对这个专栏有一个GIN索引,它似乎不会显著影响搜索时间(我现在用20k条记录进行测试,大约需要550ms)。索引如下所示:

    CREATE INDEX ix_table_1_column_jsonb_gin
      ON app.table_1 USING gin
      (column_jsonb jsonb_path_ops)
      TABLESPACE pg_default;
    
  • 我只对值感兴趣,我现在搜索它们的方式如下:

    EXISTS(SELECT value FROM jsonb_each(column_jsonb) WHERE value::text ILIKE search_term)
    
这里search_term是来自前端的变量,带有用户正在搜索的字符串

我有以下问题:

  • 是否可以在不修改数据模型的情况下加快检查速度?我已经读到,对于类似的情况,trigram索引可能是usfeul,但至少对我来说,将jsonb转换为文本然后进行检查似乎会更慢,实际上,如果列的原始类型是jsonb,并且我显式地将每一行转换为
    text
    ,我不确定trigram索引是否真的有效?如果我是苦口婆心的话,如果可能的话,我真的很想用例子来解释一下

  • 是否有一些我不知道的JSONB函数提供了我正在搜索的现成功能,我受PostgreSQL v 11.9的限制,因此版本12附带的一些新功能不适用于我

  • 如果当前的数据结构无法实现显著的改进,您能否提出一种方法来重组列中的数据\u jsonb可能是其他类型的另一列,数据以其他方式持久化,我不知道


提前非常感谢

如果数据结构是扁平的,您需要定期搜索值,并且值的类型都相同,那么传统的键/值表似乎更合适

create table table1_options (
  table1_id bigint not null references table1(id),
  key text not null,
  value text not null
);

create index table1_options_key on table1_options(key);
create index table1_options_value on table1_options(value);

select *
from table1_options
where value ilike 'some search%';
我使用了简单的B树索引,但您可以使用


缺点是所有值必须具有相同的类型(这里似乎不是问题),并且每个表都需要一个额外的表。最后一个问题可以通过以下方法有所缓解。

谢谢您的回答。但我似乎还不够清楚。事实上,我只在值中被忽略,如果搜索项包含在其中的任何一个值中。另外,我真的想问你——有没有可能直接在JSONB列上创建三元索引?@Leron_说,如果你经常搜索值,但不知道键,那么使用不同的数据结构可能会更好。键/值表将更好地工作,因为您可以简单地索引值。如果让其他人阅读,这是很好的,但在我的特定情况下,所有值都是相同的类型,这是非常不可能更改的,因此对我来说这不是一个问题。谢谢,这对我非常有用,并回答了我的所有问题。但我想请你帮个忙-我真的很感兴趣如何正确使用三角形索引在这种情况下。我已经读过了,但是我仍然不能很好地理解如何正确地创建索引和执行搜索。你能给我举个例子吗。我会非常感激的@Leron_说_get_back__Monica抱歉,我对文本搜索没有太多经验,更不用说jsonb+文本搜索了。我对jsonb的经验是,它看起来像一颗银弹,但最终会使事情变得复杂,尤其是索引。如果你不需要它,就不要使用它。你特别需要模式搜索吗?例如,
WHERE value::text我喜欢'key%'
。但需要澄清的是,在JSON键-值对中,我感兴趣的是值部分是否包含
search\u term
。只需确保在查询条件中使用与在查询条件中相同的表达式即可。三角图搜索可能不是您想要的,但它仍然可以通过提供一个选择性索引来加速查询。@Bergi我很难清楚地知道如何创建这个三角图索引。你能举例说明如何正确创建索引和执行搜索吗?我会非常感激的!请看一看近似的副本,也可以是或。当然,您有一个对象而不是数组,因此理想情况下您可能希望从索引值中删除键,但我不知道有什么好的/非黑客的方法可以做到这一点。