ElasticSearch(四)查詢、分詞器
正向索引
正排表是以文件的ID為關鍵字,表中記錄文件中每個字的位置資訊,查詢時掃描表中每個文件中字的資訊直到找出所有包含查詢關鍵字的文件。
這種組織方法在建立索引的時候結構比較簡單,建立比較方便且易於維護;因為索引是基於文件建立的,若是有新的文件加入,直接為該文件建立一個新的索引塊,掛接在原來索引檔案的後面。若是有文件刪除,則直接找到該文件號文件對應的索引資訊,將其直接刪除。但是在查詢的時候需對所有的文件進行掃描以確保沒有遺漏,這樣就使得檢索時間大大延長,檢索效率低下。
儘管正排表的工作原理非常的簡單,但是由於其檢索效率太低,除非在特定情況下,否則實用性價值不大。
倒排索引
倒排表以字或詞為關鍵字進行索引,表中關鍵字所對應的記錄表項記錄了出現這個字或詞的所有文件,一個表項就是一個字表段,它記錄該文件的ID和字元在該文件中出現的位置情況。
由於每個字或詞對應的文件數量在動態變化,所以倒排表的建立和維護都較為複雜,但是在查詢的時候由於可以一次得到查詢關鍵字所對應的所有文件,所以效率高於正排表。在全文檢索中,檢索的快速響應是一個最為關鍵的效能,而索引建立由於在後臺進行,儘管效率相對低一些,但不會影響整個搜尋引擎的效率。
正排索引是從文件到關鍵字的對映(已知文件求關鍵字),倒排索引是從關鍵字到文件的對映(已知關鍵字求文件)。
文件內容:
序號 |
文件內容 |
1 |
小俊是一家科技公司創始人,開的汽車是奧迪a8l,加速爽。 |
2 |
小薇是一家科技公司的前臺,開的汽車是保時捷911 |
3 |
小紅買了小薇的保時捷911,加速爽。 |
4 |
小明是一家科技公司開發主管,開的汽車是奧迪a6l,加速爽。 |
5 |
小軍是一家科技公司開發,開的汽車是比亞迪速銳,加速有點慢 |
倒排索引會對以上文件內容進行關鍵詞分詞,可以使用關鍵次
單詞ID |
單詞 |
倒排列表docId |
1 |
小 |
1,2,3,4,5 |
2 |
一家 |
1,2,4,5 |
3 |
科技公司 |
1,2,4,5 |
4 |
開發 |
4,5 |
5 |
汽車 |
1,2,4,5 |
6 |
奧迪 |
1,4 |
7 |
加速爽 |
1,3,4 |
8 |
保時捷 |
2,3 |
9 |
保時捷911 |
2 |
10 |
比亞迪 |
5 |
高階查詢:
根據id進行查詢
GET /mymayikt/user/12
查詢當前所有型別的文件
GET /mymayikt/user/_search
根據多個ID批量查詢
查詢多個id分別為1、2
GET /mymayikt/user/_mget
{
"ids":["1","2"]
}
複雜條件查詢
查詢年齡為年齡21歲
GET /mymayikt/user/_search?q=age:21
查詢年齡30歲-60歲之間
GET /mymayikt/user/_search?q=age[30 TO 60]
注意:TO 一定要大寫
查詢年齡30歲-60歲之間 並且年齡降序、從0條資料到第1條資料
GET /mymayikt/user/_search?q=age[30 TO 60]&sort=age:desc&from=0&size=1
查詢年齡30歲-60歲之間 並且年齡降序、從0條資料到第1條資料,展示name和age欄位
GET /mymayikt/user/_search?q=age[30 TO 60]&sort=age:desc&from=0&size=1&_source=name,age
Dsl語言查詢與過濾
什麼是DSL語言
es中的查詢請求有兩種方式,一種是簡易版的查詢,另外一種是使用JSON完整的請求體,叫做結構化查詢(DSL)。
由於DSL查詢更為直觀也更為簡易,所以大都使用這種方式。
DSL查詢是POST過去一個json,由於post的請求是json格式的,所以存在很多靈活性,也有很多形式。
Term與Match區別:
Term查詢不會對欄位進行分詞查詢,會採用精確匹配。
Match會根據該欄位的分詞器,進行分詞查詢。
根據名稱精確查詢姓名(term是代表完全匹配,即不進行分詞器分析,文件中必須包含整個搜尋的詞彙):
GET mymayikt/user/_search
{
"query": {
"term": {
"name": "xiaoming"
}
}
}
根據汽車名稱模糊查詢(match查詢相當於模糊匹配,只包含其中一部分關鍵詞就行)
GET /mymayikt/user/_search
{
"from": 0,
"size": 2,
"query": {
"match": {
"car": "奧迪"
}
}
}
使用filter過濾年齡
GET /mymayikt/user/_search
{
"query": {
"bool": {
"must": [{
"match_all": {}
}],
"filter": {
"range": {
"age": {
"gt": 21,
"lte": 51
}
}
}
}
},
"from": 0,
"size": 10,
"_source": ["name", "age"]
}
分詞器:
因為Elasticsearch中預設的標準分詞器分詞器對中文分詞不是很友好,會將中文詞語拆分成一個一箇中文的漢子。因此引入中文分詞器-es-ik外掛。
一、傳統分詞器演示:
http://192.168.212.181:9200/_analyze
//請求: { "analyzer": "standard", "text": "奧迪a4l" } //查詢結果 { "tokens": [ { "token": "奧", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "迪", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "a4l", "start_offset": 2, "end_offset": 5, "type": "<ALPHANUM>", "position": 2 } ] }
二、IK分詞外掛
下載地址: https://github.com/medcl/elasticsearch-analysis-ik/releases
注意: es-ik分詞外掛版本一定要和es安裝的版本對應
第一步:下載es的IK外掛,名改為ik.zip(上傳時候是上傳ik為名的資料夾)
第二步: 上傳到/usr/local/elasticsearch-6.4.3/plugins
第三步: 重啟elasticsearch即可
http://192.168.212.181:9200/_analyze
//請求
{
"analyzer": "ik_smart",
"text": "奧迪"
}
//查詢結果
{
"tokens": [
{
"token": "奧迪",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "a4l",
"start_offset": 2,
"end_offset": 5,
"type": "LETTER",
"position": 1
}
]
}
三、自定義擴充套件字典
(1)、在/usr/local/elasticsearch-6.4.3/plugins/ik/config目錄下
(2)、vi custom/new_word.dic(先在config目錄中建custom資料夾,把要修改的檔案放到該資料夾中,後再IKAnalyzer.cfg.xml中進行設定)
老鐵
王者榮耀
洪荒之力
共有產權房
一帶一路
餘勝軍
(3)、vi IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 擴充套件配置</comment> <!--使用者可以在這裡配置自己的擴充套件字典 --> <entry key="ext_dict">custom/new_word.dic</entry> <!--使用者可以在這裡配置自己的擴充套件停止詞字典--> <entry key="ext_stopwords"></entry> <!--使用者可以在這裡配置遠端擴充套件字典 --> <!-- <entry key="remote_ext_dict">words_location</entry> --> <!--使用者可以在這裡配置遠端擴充套件停止詞字典--> <!-- <entry key="remote_ext_stopwords">words_location</entry> --> </properties>