Elasticsearch入門和查詢語法分析(ik中文分詞)

全文搜索如今已是很常見的功能了,固然你也能夠用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.htmlapp

 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

  • match

    查詢語法以下: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

    若是想在多個字段中查找,那就須要用到multi_match查詢,語法以下:

$response = $client->get('localhost:9200/accounts/person/_search', [
    'json' => [
        'query' => [
            'multi_match' => [
                'query' => '張三 php',
                'fields' => ['title', 'desc', 'user']
            ]
        ]
    ]
]);
  • query_string

    查詢語法以下:相似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'],
            ]
        ]
    ]
]);
  • range query

    這是範圍查詢,例如查詢年齡在10到20歲之間的。查詢語法以下:

$response = $client->get('localhost:9200/accounts/person/_search', [
    'json' => [
        'query' => [
            'range' => [
                'age' => [
                    'gte' => 10,
                    'lte' => 20,
                ],
            ]
        ]
    ]
]);

gte表示>=,lte表示<=,gt表示>,lt表示<。

  • bool查詢

  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查詢是必須不知足上面兩個查詢條件。

 

以上也是我看文檔總結出來的,若有不對的地方,望大神指點。

相關文章
相關標籤/搜索