【问题标题】:Case insensitive Postgres query with array contains带有数组的不区分大小写的 Postgres 查询包含
【发布时间】:2017-04-16 02:59:13
【问题描述】:

我的记录包含如下标签数组:

   id   |                     title                     |       tags
--------+-----------------------------------------------+----------------------
 124009 | bridge photo                                  | {bridge,photo,Colors}
 124018 | Zoom 5                                        | {Recorder,zoom}
 123570 | Sint et                                       | {Reiciendis,praesentium}
 119479 | Architecto consectetur                        | {quia}

我正在使用以下 SQL 查询按标签('bridge'、'photo'、'Colors')获取特定记录:

SELECT  "listings".* FROM "listings" WHERE (tags @> ARRAY['bridge', 'photo', 'Colors']::varchar[]) ORDER BY "listings"."id" ASC LIMIT $1  [["LIMIT", 1]]

这会返回该表中的第一条记录。

问题在于我有混合类型的情况,如果我搜索:bridgephotocolors,我希望它返回相同的结果。本质上,我需要使这个搜索不区分大小写,但找不到使用 Postgres 的方法。

这是我尝试过的引发错误的 SQL 查询:

SELECT  "listings".* FROM "listings" WHERE (LOWER(tags) @> ARRAY['bridge', 'photo', 'colors']::varchar[]) ORDER BY "listings"."id" ASC LIMIT $1

这是错误:

PG::UndefinedFunction: 错误: 函数 lower(character varying[]) 不存在
提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。

【问题讨论】:

    标签: arrays postgresql


    【解决方案1】:

    您可以通过以下方式将文本数组元素转换为小写:

    select lower(tags::text)::text[]
    from listings;
    
              lower           
    --------------------------
     {bridge,photo,colors}
     {recorder,zoom}
     {reiciendis,praesentium}
     {quia}
    (4 rows)
    

    在您的查询中使用它:

    SELECT * 
    FROM listings
    WHERE lower(tags::text)::text[] @> ARRAY['bridge', 'photo', 'colors'] 
    ORDER BY id ASC;
    
       id   |    title     |         tags          
    --------+--------------+-----------------------
     124009 | bridge photo | {bridge,photo,Colors}
    (1 row) 
    

    【讨论】:

    • lower(tags::text)::text[] 当然适用于所有情况,但仍然看起来很脏
    • 脏?这是一个品味问题。脏但速度快! ;)
    【解决方案2】:

    您不能将LOWER() 直接应用于数组,但您可以解压数组,将其应用于每个元素,并在完成后重新组合:

    ... WHERE ARRAY(SELECT LOWER(UNNEST(tags))) @> ARRAY['bridge', 'photo', 'colors']
    

    你也可以安装citext (case-insensitive text) module;如果您将listings.tags 声明为citext[] 类型,则您的查询应该按原样工作。

    【讨论】:

    • 谢谢尼克,接受了另一个答案,因为它不需要安装额外的扩展。
    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 2023-03-07
    • 2020-08-20
    • 2014-03-25
    • 1970-01-01
    • 2012-02-18
    相关资源
    最近更新 更多