正向索引
正排表是以文檔的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>