博客 / 詳情

返回

需要掌握的 Laravel Eloquent 搜索技術

本文同步至個人博客 需要掌握的 Laravel Eloquent 搜索技術,轉載請註明出處。

當我們的應用程序訪問較少時(例如在項目初期階段),直接進行項目編碼就可以解決大多數問題。項目中的搜索功能也是如此,沒必要在一開始就引入完整的第三方類庫進行搜索功能支持。大多數情況下使用 Eloquent 的查詢功能就可以完成基本的搜索處理。

預熱

搜索功能是應用的重要組成模塊。優秀的設計,可以幫助我們的用户簡單快速的檢索想要的信息。因此,在項目中對搜索功能的設計,無論前端還是後端都需要提供良好的解決方案。
本文不會探討搜索功能的前端及 UI 設計等內容。若需要學習前端在搜索設計方面的知識,可以閲讀 Instant AJAX Search with Laravel and Vue 這篇文章。

本文將帶領大家學習 MySQL 和 Eloquent 在搜索模塊中設計的相關技術。

基本的 Eloquent Where 查詢

作為首個要講解的搜索功能,我們先不涉及新知識點。在 Laravel 中可以使用 where 方法實現對給定字段和給定值進行比較查詢,就是這樣簡單。

<?php

$results = Post::where('title', 'foo')->get();

甚至,你可以傳入一個 arraywhere 方法裏,對多個字段進行比較查詢。它的工作原理,類似 &&(與查詢) 運算符,當所有條件都為 true 時,返回結果集:

<?php

$results = Post::where([
            ['title' => 'foo'],
            ['published' => true],
        ])->get();

如果需要實現類似 ||(或查詢) 查詢,則可以使用 Eloquent 查詢構造器提供的 orWhere 方法。

<?php

$results = Post::where('title, 'foo')->orWhere('description', 'foo')->get();

有關 where 語句的使用方法,強烈建議閲讀 Laravel 「查詢構造器 - Where 語句」 文檔。

使用 Like 關鍵字

如何實現模糊查詢呢?即實現 MySQL 的 LIKE 查詢。Eloquent 提供了比 where 語句更加靈活的模糊查詢功能。通過在 where 方法中使用通配符,可以實現模糊查詢功能。讓我們看看 % 通配符:

<?php

$keyword = 'foo';

// 獲取以 foo 開始,以任何字符結尾的文章
$result = Post::where('title', 'like', '{$keyword}%')->get();

// 獲取以任何字符開始,但以 foo 結尾的文章
$result = Post::where('title', 'like', '%{$keyword}')->get();

// 獲取包含 foo 的文章
$result = Post::where('title', 'like', '%{$keyword}%')->get();

我們可以看到 Eloquent 的模糊查詢功能十分靈活。即可以查詢以指定字符開始或結尾的數據,也可以查詢包含指定字符的數據。模糊查詢在我們需要對依稀記得部分數據進行查詢時非常實用。

提示:
A big note here: Probably you are using a collation that ends with _ci. That means it’s case-insensitive. Whether you type FOO, Foo, fOO, etc., you get the same result!

當然,上面的查詢功能都可以在文檔中找到。

在 JSON 列中搜索

JSON 類型讓數據存儲擁有靈活性,這個功能很贊。Laravel 中也可以輕鬆執行對 JSON 數據的查詢,這得益於 Laravel 良好的 JSON 支持。
不過在深入研究之前需要注意的一點是:謹記 JSON 列的存儲是 區分大小寫 的。

而如果我們需要查詢的數據不存在 區分大小寫 的問題,可以執行類似下面的查詢語句:

<?php
$results = Post::where('meta->description', 'like', '%foo%')->get();

這條模糊查詢語句和前面的 where 查詢並無二致,對吧?但是如果我們的 JSON 數據存在 大小寫字符 的情況,又該如何處理呢?這種場景最適合使用 whereRaw 方法,先來看看示例,再來講解它工作原理:

<?php
$keyword = 'foo';
$results = Post::whereRaw('lower(meta->"$.description") like lower(?)', ['%foo%']);

你會注意到這條的查詢語句有些不同。

首先,除了 like 關鍵字外還多了些 SQL 語法,因為這裏我們傳入的是一條 原生 SQL 表達式
其次,在第 2 個 lower 函數內加入了 ? 佔位符,這種語法即為參數綁定,它的主要作用是用於防止 SQL 注入。

如你所見,我們將一個 array 給到 whereRaw 的第二個參數,數組內的第一個元素對應第一個參數綁定佔位符,第二個元素對應第二個參數綁定佔位符,以此類推。
這就是 whereRaw 的工作原理。

接下來將焦點集中到真正的關鍵處理:我們通過 MySQL 的 lower() 函數將待查詢的 JSON 數據等數據轉換成小寫字符,實現 不區分大小寫 的查詢操作。解決方案雖然實現起來較為麻煩,但工作良好。

依據單詞發音進行模糊匹配

繼續探討最後一個主題,當用户輸入的查詢表達式包含錯誤的單詞拼寫時,該如何進行搜索呢?查詢與給定的表達式有類似發音的語句是個不錯的主意。這種場景我們無法使用 like 關鍵字,但我們有 sound like 關鍵字。

先不必深究 sound like 的工作原理,但如果你真的對 sound like 功能感興趣可以閲讀 MySQL SOUNDS LIKE 這篇文章。所有你感興趣的內容它都所涉及。但現在讓我們看看 Laravel 如何使用這個功能。

<?php
$results = Post::where('title', 'sound like', 'mistyped')->get();
提示:對 MySQL sound like 功能的支持,需要使用 5.6.8 以上的 Laravel 版本,可以查看 Laravel changelog

執行 sound like 操作,會進行一個發音相似性的算法,然後獲取結果集。但是這並不是我們需要關注的,我們僅需將待查詢的字符串傳給 where 語句即可。返回的結果集即會包含完全匹配的數據,也會包含發音近似的數據。

總結

Laravel 為我們提供了簡單實用的查詢功能。我們可以在 Laravel 裏使用 where 語句,可以使用原生 SQL 語句,甚至可以使用模糊查詢和相似查詢,所有這些查詢功能都是 Laravel 內置提供的開箱即用,非常贊!

user avatar dominic-giglio 頭像 abei2017 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.