本教程探讨了在 Laravel 8 中进行多字段模糊搜索时,如何有效处理包含空格的复合查询字符串。通过将搜索值拆分为多个关键词并循环应用 `orWhere` 条件,解决了传统 `orWhere` 链无法匹配姓名等复合字段的问题,显著提升了搜索的灵活性和准确性。
在 Laravel 应用程序中,数据库搜索是常见的功能需求。利用 Eloquent ORM 和查询构建器,开发者可以轻松地构建复杂的数据库查询。然而,当用户需要在一个搜索框中输入包含多个词语(例如“名 姓”)的复合查询,并且这些词语可能分散在数据库的不同字段(如 name 和 surname)时,传统的 orWhere 链式查询可能会遇到问题。
考虑以下场景:用户希望搜索名为“Karol Krawczyk”的记录。如果数据库中存在 name 字段为“Karol”且 surname 字段为“Krawczyk”的记录,但使用单个搜索字符串“Karol Krawczyk”进行查询时,却无法得到结果。这是因为默认的 LIKE 查询会将整个字符串作为一个整体进行匹配,例如 immovables.name LIKE "%Karol Krawczyk%",这显然无法匹配到 name 字段只有“Karol”的情况。
以下是原始的查询代码示例,它展示了对单个搜索值应用多个 orWhere 条件的常见模式:
$query = Immovable::query()
->leftJoin('streets', 'streets.gus_id', '=', 'immovables.street_gus_id')
->select('immovables.id',
'immovables.street_gus_id',
'immovables.building_number',
'immovables.apartment_number',
'streets.name as street_name'
);
if (request()->has('search')) {
// 假设 $request->search['value'] 为 "Karol Krawczyk"
$searchValue = $request->search['value'];
$query->where('streets.name', 'like', "%" . $searchValue . "%");
$query->orWhere('immovables.community', 'like', "%" . $searchValue . "%");
// ... 其他字段
$query->orWhere('immovables.name', 'like', "%" . $searchValue . "%"); // 匹配 "%Karol Krawczyk%"
$query->orWhere('immovables.surname', 'like', "%" . $searchValue . "%"); // 匹配 "%Karol Krawczyk%"
// ... 更多字段
}
$query->get();这段代码能够正常工作,但当 $searchValue 包含空格时,它会将整个字符串作为单个匹配模式,导致无法找到分散在不同字段中的独立词语。
当用户输入“Karol Krawczyk”时,上述代码会生成类似 WHERE immovables.name LIKE "%Karol Krawczyk%" 或 OR immovables.surname LIKE "%Karol Krawczyk%" 的 SQL 条件。如果数据库中 immovables.name 字段的值是“Karol”,immovables.surname 字段的值是“Krawczyk”,那么这些条件都不会匹配成功,因为没有一个字段完整包含“Karol Krawczyk”这个字符串。
要解决这个问题,我们需要将用户输入的复合搜索词拆分成独立的关键词,并对每个关键词分别应用多字段的 OR 搜索逻辑。这样,无论是“Karol”匹配 name 字段还是“Krawczyk”匹配 surname 字段,都能被正确检索到。
核心思想是:将用户输入的搜索字符串按空格拆分成多个独立的关键词。然后,遍历这些关键词,为每个关键词构建一组 OR 条件,应用到所有需要搜索的字段上。最终,所有关键词的所有搜索条件将通过 OR 逻辑连接起来。
具体步骤如下:
以下是优化后的 Laravel 查询代码示例:
use Illuminate\Http\Request; // 确保引入 Request 类
// 假设这段代码在一个控制器方法中
public function searchImmovables(Request $request)
{
$query = Immovable::query()
->leftJoin('streets', 'streets.gus_id', '=', 'immovables.street_gus_id')
->select(
'immovables.id',
'immovables.street_gus_id',
'immovables.building_number',
'immovables.apartment_number',
'streets.name as street_name'
);
if ($request->has('search') && !empty($request->search['value'])) {
$searches = explode(" ", $request->search['value']); // 拆分搜索值
foreach ($searches as $index => $search) {
// 对每个关键词进行处理,确保去除空白字符
$search = trim($search);
if (empty($search)) {
continue; // 跳过空关键词
}
// 构建条件组:
// 对于第一个关键词,其第一个字段使用 where(),后续字段使用 orWhere()
// 对于后续关键词,所有字段都使用 orWhere()
if ($index === 0) {
// 第一个关键词的第一个条件使用 WHERE
$query->where('streets.name', 'like', "%" . $search . "%");
} else {
// 后续关键词的第一个条件以及所有后续条件使用 OR WHERE
$query->orWhere('streets.name', 'like', "%" . $search . "%");
}
// 对所有其他字段应用 OR WHERE 条件
$query->orWhere('immovables.community', 'like', "%" . $search . "%");
$query->orWhere('immovables.city', 'like', "%" . $search . "%");
$query->orWhere('immovables.building_number', 'like', "%" . $search . "%");
$query->orWhere('immovables.granted_comments', 'like', "%" . $search . "%");
$query->orWhere('immovables.inspections', 'like', "%" . $search . "%");
$query->orWhere('immovables.oze_installations', 'like', "%" . $search . "%");
$query->orWhere('immovables.pesel', 'like', "%" . $search . "%");
$query->orWhere('immovables.name', 'like', "%" . $search . "%");
$query->orWhere('immovables.surname', 'like', "%" . $search . "%");
$query->orWhere('immovables.email1', 'like', "%" . $search . "%");
$query->orWhere('immovables.email2', 'like', "%" . $search . "%");
$query->orWhere('immovables.email3', 'like', "%" . $search . "%");
$query->orWhere('immovables.phone1', 'like', "%" . $search . "%");
$query->orWhere('immovables.phone2', 'like', "%" . $search . "%");
$query->orWhere('immovables.phone3', 'like', "%" . $search . "%");
$query->orWhere('immovables.description', 'like', "%" . $search . "%");
}
}
$results = $query->get();
return response()->json($results);
}代码解析:
通过这种方式,如果用户搜索“Karol Krawczyk”,最终的 SQL 查询逻辑大致会是: (streets.name LIKE '%Karol%' OR immovables.community LIKE '%Karol%' OR ... OR immovables.name LIKE '%Karol%' OR immovables.surname LIKE '%Karol%') OR (streets.name LIKE '%Krawczyk%' OR immovables.community LIKE '%Krawczyk%' OR ... OR immovables.name LIKE '%Krawczyk%' OR immovables.surname LIKE '%Krawczyk%')
这样,只要“Karol”在任何一个指定字段中找到,或者“Krawczyk”在任何一个指定字段中找到,该记录都会被返回,从而解决了复合搜索词的匹配问题。
查询性能:当搜索字段数量众多且数据量庞大时,大量的 OR 条件可能会导致查询性能下降。确保所有参与搜索的数据库字段都建立了合适的索引(尤其是 LIKE 查询常用的 B-tree 索引或全文索引,具体取决于数据库类型和查询模式)。
SQL 逻辑分组:上述解决方案将所有条件简单地通过 OR 连接。如果需要更精细的逻辑分组,例如“(关键词A在字段X或字段Y中)AND(关键词B在字段X或字段Y中)”,则需要使用 Eloquent 的闭包 where(function($query){ ... }) 来嵌套和分组条件。 例如,要实现 (field1 LIKE %Karol% OR field2 LIKE %Karol%) AND (field1 LIKE %Krawczyk% OR field2 LIKE %Krawczyk%) 这种逻辑,代码会更复杂:
if ($request->has('search') && !empty($request->search['value'])) {
$searches = explode(" ", $request->search['value']);
foreach ($searches as $search) {
$search = trim($search);
if (empty($search)) continue;
$query->where(function ($subQuery) use ($search) {
$subQuery->where('streets.name', 'like', "%" . $search . "%")
->orWhere('immovables.community', 'like', "%" . $search . "%")
// ... 其他字段
->orWhere('immovables.name', 'like', "%" . $search . "%")
->orWhere('immovables.surname', 'like', "%" . $search . "%");
});
}
}这种方式会生成 (cond_for_Karol) AND (cond_for_Krawczyk) 的逻辑。然而,对于本教程解决的“Karol Krawczyk”问题,原始的 OR 逻辑通常更符合预期,因为它意味着只要找到任何一个词的任何一个匹配即可。
用户体验:可以考虑对用户输入的搜索词进行预处理,例如转换为小写(如果数据库不区分大小写或使用不区分大小写的排序规则)、去除多余空格、甚至支持同义词替换等,以提升搜索的准确性和用户体验。
全文搜索:对于更高级的文本搜索需求,例如词干提取、相关性排序等,可以考虑使用数据库自带的全文搜索功能(如 MySQL 的 FULLTEXT 索引、PostgreSQL 的 tsvector 和 tsquery)或集成专门的搜索服务(如 Elasticsearch、Algolia)。
通过将复合搜索字符串拆分为独立的关键词,并对每个关键词应用多字段的 O
R 条件,我们成功地解决了 Laravel 中多字段模糊搜索无法匹配包含空格的复合查询的问题。这种方法提高了搜索的灵活性和准确性,使得用户能够更自然地进行搜索。在实际应用中,开发者应根据具体需求权衡查询性能和功能复杂度,并考虑使用索引优化和更高级的搜索技术。
# mysql
# laravel
# js
# json
# go
# ai
# sql
# if
# foreach
# continue
# 字符串
# 循环
# 闭包
# function
# elasticsearch
# postgresql
# 数据库
# 关键词
# 第一个
# 多字
# 多个
# 任何一个
# 遍历
# 会将
# 这段
# 解决了
# 并对
相关文章:
建站主机服务器选购指南:轻量应用与VPS配置解析
建站主机解析:虚拟主机配置与服务器选择指南
零基础网站服务器架设实战:轻量应用与域名解析配置指南
电脑免费海报制作网站推荐,招聘海报哪个网站多?
定制建站模板如何实现SEO优化与智能系统配置?18字教程
如何安全更换建站之星模板并保留数据?
网站设计制作企业有哪些,抖音官网主页怎么设置?
如何在宝塔面板中修改默认建站目录?
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
建站主机SSH密钥生成步骤及常见问题解答?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
招商网站制作流程,网站招商广告语?
建站之星在线客服如何快速接入解答?
建站之星安装需要哪些步骤及注意事项?
学校免费自助建站系统:智能生成+拖拽设计+多端适配
免费网站制作模板下载,除了易企秀之外还有什么H5平台可以制作H5长页面,最好是免费的?
家庭服务器如何搭建个人网站?
建站主机与虚拟主机有何区别?如何选择最优方案?
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些?
建站org新手必看:2024最新搭建流程与模板选择技巧
专业商城网站制作公司有哪些,pi商城官网是哪个?
成都网站制作价格表,现在成都广电的单独网络宽带有多少的,资费是什么情况呢?
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
如何选择适配移动端的WAP自助建站平台?
攀枝花网站建设,攀枝花营业执照网上怎么年审?
PHP正则匹配日期和时间(时间戳转换)的实例代码
山东云建站价格为何差异显著?
代购小票制作网站有哪些,购物小票的简要说明?
家具网站制作软件,家具厂怎么跑业务?
北京网站制作的公司有哪些,北京白云观官方网站?
北京网站制作网页,网站升级改版需要多久?
制作网站公司那家好,网络公司是做什么的?
武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?
大同网页,大同瑞慈医院官网?
韩国服务器如何优化跨境访问实现高效连接?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
如何选择建站程序?包含哪些必备功能与类型?
高端云建站费用究竟需要多少预算?
高防服务器租用如何选择配置与防御等级?
已有域名如何免费搭建网站?
建站之星展会模版如何一键下载生成?
相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?
建站主机选虚拟主机还是云服务器更好?
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
如何在Golang中引入测试模块_Golang测试包导入与使用实践
婚礼视频制作网站,学习*后期制作的网站有哪些?
*请认真填写需求信息,我们会在24小时内与您取得联系。