You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:17:09