全文搜索如今已是很常見的功能了,固然你也能夠用mysql加Sphinx實現。但開源的Elasticsearch(簡稱ES)目前是全文搜索引擎的首選。目前像GitHub、維基百科都使用的是ES,它能夠快速的存儲,搜索和分析數據。php
1、安裝與啓動html
ES的運行須要依賴java環境,能夠在命令行運行 java --version 。若是出現java
說明已經安裝了,不然你就須要安裝下java環境。mysql
而後咱們就能夠開始裝ES了。一、能夠用docker容器安裝。二、用壓縮包安裝。sql
我是用壓縮包安裝的。docker
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.1.tar.gz tar -xzf elasticsearch-6.3.1.tar.gz cd elasticsearch-6.3.1/
而後輸入 ./bin/elasticsearch 就能夠啓動ES了。在瀏覽器上輸入 localhost:9200 ,若是出現json
就說明ES成功跑起來了。瀏覽器
不瞭解ES的同窗能夠去看看阮老師的這篇文章http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html。app
2、IK分詞curl
ES默認的分詞是英文分詞,對中文分詞支持的並很差。因此咱們就須要安裝ik中文分詞。讓咱們看看區別。
在這裏須要說明的一點時,ES不少API請求都是GET帶上了Request Body。因此經過瀏覽器或者postman等工具發起GET請求時會報錯。有兩種方法能夠解決。
一、經過命令含的curl請求。
curl -X GET "localhost:9200/_analyze" -H 'Content-Type: application/json' -d' { "analyzer" : "standard", "text" : "this is a test" } '
二、在代碼中經過curl請求。
// 經過php的guzzle包發起的請求
$client = new Client(); $response = $client->get('localhost:9200/_analyze', [ 'json' => [ 'analyzer' => 'standard', 'text' => "功能進階", ] ]); $res = ($response->getBody()->getContents());
而後咱們來看看ik中文分詞和ES默認的分詞區別。一樣是上面的請求
ES默認分詞結果
{ "tokens": [ { "token": "功", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "能", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "進", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2 }, { "token": "階", "start_offset": 3, "end_offset": 4, "type": "<IDEOGRAPHIC>", "position": 3 } ] }
ik中文分詞結果
ik分詞也分兩種分析器。ik_smart:儘量少的進行中文分詞。ik_max_word:儘量多的進行中文分詞。
$response = $client->get('localhost:9200/_analyze', [ 'json' => [ 'analyzer' => 'ik_max_word', 'text' => "功能進階", ] ]);
獲得的結果爲:
{ "tokens": [ { "token": "功能", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 1 }, { "token": "能進", "start_offset": 1, "end_offset": 3, "type": "CN_WORD", "position": 2 }, { "token": "進階", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 3 } ] }
而ik_smart
$response = $client->get('localhost:9200/_analyze', [ 'json' => [ 'analyzer' => 'ik_smart', 'text' => "功能進階", ] ]);
的結果爲
{ "tokens": [ { "token": "功能", "start_offset": 0, "end_offset": 2, "type": "CN_WORD", "position": 1 }, { "token": "進階", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 3 } ] }
其實他們的區別經過名字你也能夠略知一二。哈哈。。。
假若有人想問,我就想把「功能進階」當成一個詞來搜索,能夠嗎?
Of course!!
這時候咱們就要自定義分詞。進入你的ES目錄,運行 cd config/analysis-ik/ 進去ik分詞的配置。找到IKAnalyzer.cfg.xml文件,而後 vi IKAnalyzer.cfg.xml 。
我在 elasticsearch-6.3.0/config/analysis-ik 目錄下,建立了 custom/mydict.dic ,而後添加到上圖的紅色框框中,這就是你自定義分詞的文件。若是有多個文件,能夠用英文分號(;)隔開。
能夠看到,我在自定義中文分詞文件中添加了「功能進階」這個詞。這時候用ik_smart分析器的結果是:
{ "tokens": [ { "token": "功能進階", "start_offset": 0, "end_offset": 4, "type": "CN_WORD", "position": 0 } ] }
很好,這就是咱們想要的。
3、Query DSL
查詢語法以下:title是須要查詢的字段名,能夠被替換成任何字段。query對應的是所需的查詢。好比這裏會被拆分紅‘php’和‘後臺’,應爲operator是or,因此ES會去全部數據裏的title字段查詢包含‘後臺’和‘php’的,若是operator爲and,這查詢的是即包含‘後臺’又有‘php’的數據,這應該很好理解。
$response = $client->get('localhost:9200/accounts/person/_search', [ 'json' => [ 'query' => [ 'match' => [ 'title' => [ 'query' => '後臺php', 'operator' => 'or', ] ] ] ] ]);
若是想在多個字段中查找,那就須要用到multi_match查詢,語法以下:
$response = $client->get('localhost:9200/accounts/person/_search', [ 'json' => [ 'query' => [ 'multi_match' => [ 'query' => '張三 php', 'fields' => ['title', 'desc', 'user'] ] ] ] ]);
查詢語法以下:相似match查詢的operator,在這裏須要在query中用OR或AND實現。
$response = $client->get('localhost:9200/accounts/person/_search', [ 'json' => [ 'query' => [ 'query_string' => [ 'query' => '(張三) OR (php)', 'default_field' => 'title', ] ] ] ]);
多字段查詢以下:
$response = $client->get('localhost:9200/accounts/person/_search', [ 'json' => [ 'query' => [ 'query_string' => [ 'query' => '(張三) OR (php)', 'fields' => ['title', 'user'], ] ] ] ]);
這是範圍查詢,例如查詢年齡在10到20歲之間的。查詢語法以下:
$response = $client->get('localhost:9200/accounts/person/_search', [ 'json' => [ 'query' => [ 'range' => [ 'age' => [ 'gte' => 10, 'lte' => 20, ], ] ] ] ]);
gte表示>=,lte表示<=,gt表示>,lt表示<。
bool查詢的語法都是同樣的。以下:
$response = $client->get('localhost:9200/accounts/person/_search', [ 'json' => [ 'query' => [ 'bool' => [ 'must/filter/should/must_not' => [ [ 'query_string' => [ 'query' => '研發', ] ], [ 'range' => [ 'age' => [ 'gt' => 20 ] ] ], ], ] ] ] ]);
1)must:must查詢是查詢字段中必須知足上面兩個條件,而且會計算到score中。
2)filter:filter查詢與must同樣,都必須知足上面兩個條件,只不過查詢結果不會計算score,也就是score始終爲0.
3)should:should查詢只須要知足上面兩種查詢條件中的一種便可。
4)must_not:must_not查詢是必須不知足上面兩個查詢條件。
以上也是我看文檔總結出來的,若有不對的地方,望大神指點。