Laravel基于MariaDB全文搜索结果按相关性排序实现方法
在Laravel中基于MariaDB实现全文搜索并按相关性排序
当前已实现基本的全文搜索分页功能,但需要让搜索结果按与关键词的相关性排序,使最匹配的结果排在前面。以下是现有代码:
迁移文件
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { public function up(): void { Schema::dropIfExists('posts'); Schema::create('posts',function (Blueprint $table){ // More columns will be added in next migrations. $table->id(); $table->string('name'); $table->fulltext(['name']); }); } public function down(): void { Schema::dropIfExists('posts'); } };
模型代码
namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Post extends Model { use HasFactory; protected $table="posts"; }
控制器搜索代码
class PostController extends Controller { public function search() { $searchterm = $request->get('searchterm'); $qb = Post::query(); if(!empty($searchterm)){ $qb=$qb->whereFullText(['name'],$searchterm); } $page = $request->get('page')??1; $limit = $request->get('limit')??20; $results = $qb->offset(($page - 1) * $limit) ->simplePaginate($limit); return new JsonResponse($results,200); } }
实现按相关性排序的方法
MariaDB的全文搜索支持通过MATCH() AGAINST()函数计算相关性得分,我们可以利用这个得分对结果进行排序,具体修改如下:
1. 修改控制器搜索逻辑
在添加全文搜索条件后,新增相关性得分计算与排序逻辑:
class PostController extends Controller { public function search(Request $request) // 补充Request依赖注入,修复原代码变量未定义问题 { $searchterm = $request->get('searchterm'); $qb = Post::query(); if(!empty($searchterm)){ // 添加全文搜索条件,同时计算相关性得分 $qb->whereFullText(['name'], $searchterm) ->selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS relevance', [$searchterm]) ->orderBy('relevance', 'desc'); } else { // 无搜索词时设置默认排序,避免结果无序 $qb->orderBy('id', 'desc'); } $page = $request->get('page') ?? 1; $limit = $request->get('limit') ?? 20; $results = $qb->simplePaginate($limit); return new JsonResponse($results, 200); } }
关键说明
selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS relevance', [$searchterm]):通过MATCH() AGAINST()函数计算每条记录与搜索词的相关性得分,并将该得分命名为relevance字段。使用IN BOOLEAN MODE既支持灵活的搜索语法(如前缀匹配、排除关键词),也能稳定输出相关性得分。orderBy('relevance', 'desc'):按照相关性得分从高到低排序,确保最匹配的结果排在最前面。- 补充
Request $request依赖注入:原代码中未注入Request实例,会导致$request变量未定义的错误,需修正。
2. 分页兼容性说明
使用simplePaginate时,Laravel会自动在排序完成后处理分页逻辑,相关性计算不会影响分页功能的正常运行。
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

