简体   繁体   English

在 postgres 中对 jsonb 数组数据进行索引的 ILIKE 查询

[英]ILIKE query with indexing for jsonb array data in postgres

I have table in which has city as jsonb column which has json array like below我有一个表格,其中城市为 jsonb 列,其中有 json 数组,如下所示

[{"name":"manchester",..},{"name":"liverpool",....}]

now I want to query table on "name" column with ILIKE query.现在我想用 ILIKE 查询查询“名称”列上的表。

I have tried with below but it is not working for me我在下面尝试过,但它对我不起作用

select * from data where city->>'name' ILIKE '%man%'

while i know, I can search with exact match by below query虽然我知道,但我可以通过以下查询进行完全匹配的搜索

select * from data where city->>'name' @> 'manchester'

Also I know we can jsonb functions to make it flat data and search but it will not use than indexing.我也知道我们可以使用 jsonb 函数来使其成为平面数据和搜索,但它不会比索引使用。

is there anyway to search data with ilike in a way it also use indexing?有没有用 ilike 搜索数据的方式,它也使用索引?

Index support will be difficult;指数支撑将是困难的; for that, a schema that adheres to the first normal form would be beneficial.为此,遵循第一范式的模式将是有益的。

Other than that, you can use the JSONPATH language from v12 on:除此之外,您可以使用 v12 中的 JSONPATH 语言:

WITH t(c) AS (
   SELECT '[{"name":"manchester"},{"name":"liverpool"}]'::jsonb
)
SELECT jsonb_path_exists(
          c,
          '$.**.name ? (@ like_regex "man" flag "i")'::jsonpath
       )
FROM t;

 jsonb_path_exists 
═══════════════════
 t
(1 row)

You should really store your data differently.你真的应该以不同的方式存储你的数据。

You can do the ilike query "naturally" but without index support, like this:您可以“自然地”执行 ilike 查询,但无需索引支持,如下所示:

select * from data where exists (select 1 from jsonb_array_elements(city) f(x) where x->>'name' ILIKE '%man%');

You can get index support like this:您可以像这样获得索引支持:

create index on data using gin ((city::text) gin_trgm_ops);
select * from data where city::text ilike '%man%';

But it will find matches within the text of the keys, as well as the values, and using irrelevant keys/values of any are present.但它会在键的文本和值中找到匹配项,并使用任何不相关的键/值。 You could get around this by creating a function that returns just the values, all banged together into one string, and then use a functional index.您可以通过创建一个仅返回值的 function 来解决此问题,所有这些值都组合成一个字符串,然后使用功能索引。 But the index will get less effective as the length of the string gets longer, as there will be more false positives that need to be tracked down and weeded out.但是随着字符串的长度变长,索引的有效性会降低,因为会有更多的误报需要被追踪和清除。

create or replace function concat_val(jsonb, text) returns text immutable language sql as $$
    select string_agg(x->>$2,'   ') from jsonb_array_elements($1) f(x)
$$ parallel safe;

create index on data using gin (concat_val(city,'name')  gin_trgm_ops);

select * from data where concat_val(city,'name') ilike '%man%';

You should really store your data differently.你真的应该以不同的方式存储你的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM