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

Laravel与MySQL多列高级搜索:组合词层级匹配需求

Alright, let's break down how to build this priority-based advanced search for your Laravel application. We'll cover both Eloquent (the Laravel way) and raw SQL approaches, since you mentioned either is acceptable.

Laravel Eloquent Implementation

First, we can define a query scope in your corresponding model (let's assume it's an Article model) to make this search logic reusable across your app.

Here's the implementation that follows your priority rules:

public function scopeAdvancedSearch($query, $searchString)
{
    $words = array_filter(explode(' ', trim($searchString))); // Filter out empty strings from extra spaces
    $wordCount = count($words);

    // Only support multi-word combinations; return empty if less than 2 words
    if ($wordCount < 2) {
        return $query->whereRaw('1=0');
    }

    // 1. First priority: Match the full query string
    $fullMatchQuery = clone $query;
    $fullMatchResults = $fullMatchQuery->where(function($q) use ($searchString) {
        $q->where('title', 'LIKE', "%{$searchString}%")
          ->orWhere('short_title', 'LIKE', "%{$searchString}%")
          ->orWhere('content', 'LIKE', "%{$searchString}%")
          ->orWhere('reporter', 'LIKE', "%{$searchString}%");
    })->get();

    if ($fullMatchResults->isNotEmpty()) {
        return $fullMatchResults;
    }

    // 2. Second priority: Match the first two words
    $firstTwoWords = implode(' ', array_slice($words, 0, 2));
    $firstTwoMatchQuery = clone $query;
    $firstTwoResults = $firstTwoMatchQuery->where(function($q) use ($firstTwoWords) {
        $q->where('title', 'LIKE', "%{$firstTwoWords}%")
          ->orWhere('short_title', 'LIKE', "%{$firstTwoWords}%")
          ->orWhere('content', 'LIKE', "%{$firstTwoWords}%")
          ->orWhere('reporter', 'LIKE', "%{$firstTwoWords}%");
    })->get();

    if ($firstTwoResults->isNotEmpty()) {
        return $firstTwoResults;
    }

    // 3. Third priority: Match the last two words
    $lastTwoWords = implode(' ', array_slice($words, -2));
    return $query->where(function($q) use ($lastTwoWords) {
        $q->where('title', 'LIKE', "%{$lastTwoWords}%")
          ->orWhere('short_title', 'LIKE', "%{$lastTwoWords}%")
          ->orWhere('content', 'LIKE', "%{$lastTwoWords}%")
          ->orWhere('reporter', 'LIKE', "%{$lastTwoWords}%");
    })->get();
}

To use this in your controller, it's as simple as:

$searchResults = Article::advancedSearch('Shaikh Shamim Reza')->get();

Quick Optimization Tip

If you're working with a large dataset, replace the LIKE clauses with full-text search for better performance. Add full-text indexes to your title, short_title, reporter, and content columns, then modify the where clauses like this:

$q->whereRaw("MATCH(title, short_title, reporter) AGAINST(? IN BOOLEAN MODE)", [$searchString])
  ->orWhereRaw("MATCH(content) AGAINST(? IN BOOLEAN MODE)", [$searchString]);

Raw SQL Implementation

If you prefer using raw SQL, here are two practical approaches:

Approach 1: Step-by-Step Priority Check

This runs queries in order of priority, stopping as soon as it finds results:

SET @search_string = 'Shaikh Shamim Reza';
SET @first_two = SUBSTRING_INDEX(@search_string, ' ', 2);
SET @last_two = SUBSTRING_INDEX(@search_string, ' ', -2);

-- 1. Check full string match first
SELECT * FROM your_table
WHERE title LIKE CONCAT('%', @search_string, '%')
   OR short_title LIKE CONCAT('%', @search_string, '%')
   OR content LIKE CONCAT('%', @search_string, '%')
   OR reporter LIKE CONCAT('%', @search_string, '%')
LIMIT 100; -- Adjust limit as needed

-- If no full matches, check first two words
IF ROW_COUNT() = 0 THEN
    SELECT * FROM your_table
    WHERE title LIKE CONCAT('%', @first_two, '%')
       OR short_title LIKE CONCAT('%', @first_two, '%')
       OR content LIKE CONCAT('%', @first_two, '%')
       OR reporter LIKE CONCAT('%', @first_two, '%')
    LIMIT 100;
END IF;

-- If still no matches, check last two words
IF ROW_COUNT() = 0 THEN
    SELECT * FROM your_table
    WHERE title LIKE CONCAT('%', @last_two, '%')
       OR short_title LIKE CONCAT('%', @last_two, '%')
       OR content LIKE CONCAT('%', @last_two, '%')
       OR reporter LIKE CONCAT('%', @last_two, '%')
    LIMIT 100;
END IF;

Approach 2: Single Query with Priority Sorting

This returns all matching results sorted by priority, so you only get the highest-priority matches first:

SET @search_string = 'Shaikh Shamim Reza';
SET @first_two = SUBSTRING_INDEX(@search_string, ' ', 2);
SET @last_two = SUBSTRING_INDEX(@search_string, ' ', -2);

SELECT *,
    CASE
        WHEN (title LIKE CONCAT('%', @search_string, '%') OR short_title LIKE CONCAT('%', @search_string, '%') OR content LIKE CONCAT('%', @search_string, '%') OR reporter LIKE CONCAT('%', @search_string, '%')) THEN 1
        WHEN (title LIKE CONCAT('%', @first_two, '%') OR short_title LIKE CONCAT('%', @first_two, '%') OR content LIKE CONCAT('%', @first_two, '%') OR reporter LIKE CONCAT('%', @first_two, '%')) THEN 2
        WHEN (title LIKE CONCAT('%', @last_two, '%') OR short_title LIKE CONCAT('%', @last_two, '%') OR content LIKE CONCAT('%', @last_two, '%') OR reporter LIKE CONCAT('%', @last_two, '%')) THEN 3
        ELSE 4
    END AS priority
FROM your_table
WHERE priority IN (1,2,3)
ORDER BY priority ASC
LIMIT 100;

内容的提问来源于stack exchange,提问作者Shaikh Shamim Reza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:56:42