Laravel Eloquent实现PostgreSQL不区分大小写的whereIn查询
解决方案:Laravel Eloquent实现PostgreSQL不区分大小写的whereIn查询
针对你遇到的问题——用Laravel Eloquent的whereIn无法实现不区分大小写的标签名称匹配,结合PostgreSQL的特性,这里有几个靠谱的解决办法:
方法1:使用PostgreSQL的ILIKE ANY语法
PostgreSQL原生支持ILIKE进行不区分大小写的匹配,搭配ANY可以直接匹配数组中的元素,非常适合你的场景:
$tags = Category::whereRaw('name ILIKE ANY (?)', [$tag_names]) ->pluck('id') ->toArray();
这个写法会生成类似SELECT id FROM categories WHERE name ILIKE ANY (ARRAY['Tag1', 'tag2', 'TAG3'])的SQL,自动忽略大小写匹配数组中的所有名称。
方法2:统一转换为小写后用whereIn
另一种思路是把数据库中的name字段和查询数组都转换为小写,再用普通的whereIn匹配:
// 先把查询数组转成小写 $lowerTagNames = array_map('strtolower', $tag_names); // 用DB::raw转换数据库字段为小写 $tags = Category::whereIn(DB::raw('LOWER(name)'), $lowerTagNames) ->pluck('id') ->toArray();
如果你的categories表数据量比较大,建议给LOWER(name)创建一个函数索引来提升查询性能:
CREATE INDEX idx_categories_name_lower ON categories (LOWER(name));
这个方案的优势是查询性能更稳定,尤其是在有索引加持的情况下。
方法3:循环添加orWhere(适合小批量数据)
如果你的$tag_names数组元素不多,也可以通过循环添加不区分大小写的orWhere条件:
$query = Category::query(); foreach ($tag_names as $name) { $query->orWhere('name', 'ILIKE', $name); } $tags = $query->pluck('id')->toArray();
不过要注意,当数组元素较多时,这种方式会生成很长的SQL语句,性能不如前两种方法,只推荐小数据量场景使用。
内容的提问来源于stack exchange,提问作者Daniel Marques




