Postgres,使用 ILIKE 运算符从 json 数组中搜索的效果与从常规表中搜索不同

问题描述 投票:0回答:1

在我们的数据库中,我们的表有 6-8 M 条记录,这些数据是静态的,为了性能优化,我们决定将此表中的一些数据存储在单独的表中,对于预定义的过滤器,使用此表中的值。例如,我们想在此表中存储不同的州、城市、标签。

数据示例可以用这样的测试表来表示:

CREATE TABLE test_data_table (
                                 id    BIGSERIAL PRIMARY KEY,
                                 state  text,
                                 city text
);

INSERT INTO test_data_table (state, city)
    values  ('MD', 'Union Bridge'),
            ('IL', 'Bourbonnais'),
            ('NC', 'Rdelk'),
            ('FL', 'Bonita Springs'),
            ('FL', 'Unit Ave Maria'),
            ('AZ', 'N Placita Chula Vista Tucson'),
            ('TX', 'Sienna'),
            ('LA', 'Lornager'),
            ('CA', 'Empire'),
            ('MA', 'Middleton'),
            ('CO', 'Yampa'),
            ('GA', 'Spr Project Name Unit'),
            ('IN', 'Greencastle'),
            ('NV', 'Flora'),
            ('RI', 'Coventry'),
            ('WA', 'Rice'),
            ('FL', 'Orange City'),
            ('TX', 'Haltom City'),
            ('CA', 'Moraga'),
            ('LA', 'Belle Chasse'),
            ('AZ', 'E Rincon Creek Ranch Rd Tucson'),
            ('CA', 'Acampo'),
            ('AZ', 'S Avra Rd Tucson'),
            ('GA', 'Folkston'),
            ('FL', 'Biscayne Park'),
            ('FL', 'All Units Oxford'),
            ('IL', 'Volo'),
            ('MN', 'Peterson'),
            ('LA', 'Rayville'),
            ('KY', 'South Park View'),
            ('AZ', 'E Camino Emmanuel Sahuarita'),
            ('CA', 'Wrighwood'),
            ('CA', 'Los Angeles'),
            ('AZ', 'N Teal Blue Tr Tucson'),
            ('NY', 'Clifton Park'),
            ('IN', 'Frankl'),
            ('KY', 'Anchorage'),
            ('LA', 'Crown Point'),
            ('CA', 'Los BanosStruct CalcsSpan T'),
            ('IL', 'Chebanse');

这里是过滤器单独表格的示例以及用值填充它的方法:

    CREATE TABLE test_filter_values
(
    id    BIGSERIAL PRIMARY KEY,
    type  text,
    value jsonb
);

INSERT INTO test_filter_values (type, value)
VALUES ('CITY', (SELECT json_agg(DISTINCT city)::jsonb FROM test_data_table));

INSERT INTO test_filter_values (type, value)
VALUES ('STATE', (SELECT json_agg(DISTINCT state)::jsonb FROM test_data_table));

所以,主要问题发生在我们尝试从此表中查询数据时,这里是示例:

    SELECT DISTINCT city from test_data_table
WHERE city ILIKE 'b%';

该查询返回4条结果; 还有这个:

    SELECT city FROM (SELECT jsonb_array_elements(value) AS city
                  FROM test_filter_values WHERE type = 'CITY') cities
WHERE city::text ILIKE 'b%';

没有返回结果, 开头或结尾不带 % 的 LIKE 运算符从 test_filter_values 表中返回零结果,但如果在这种情况下使用

LIKE '%b%'
,则行为是相同的。完全匹配也会出现同样的问题:

    SELECT state FROM (SELECT jsonb_array_elements(value) AS state
                  FROM test_filter_values WHERE type = 'STATE') states
WHERE state::text = 'NC';
enter code here

它也没有返回任何结果。

那么遇到这种情况我们该如何处理呢?

sql postgresql query-optimization jsonb jsonb-array-elements
1个回答
0
投票

那是因为

jsonb_array_elements
返回 jsonb 而不是文本。 JSON 数组中可能包含其他数组、对象、对象数组等。

这意味着文本值将被引用为 JSON,当转换为文本时,您将尝试与

"Anchorage"
而非
Anchorage
进行匹配。

如果您想使用的话,也许只存储一个文本数组?

© www.soinside.com 2019 - 2024. All rights reserved.