ES004-Elasticsearch高級查詢及分詞器


1. ES操作方法

1、在可視化界面Kibana上執行代碼:

GET _search
{
  "query": {
    "match_all": {}
  }
}

PUT /mytest/user/1
{
  "name": "xj",
  "age": 21,
  "sex": 0,
  "car": "奧迪a6l"
}

GET /mytest/user/1

2、使用RESTful創建文檔

路徑:/索引/類型/id

GET命令-查詢:

方法:get

地址:http://192.168.170.128:9200/mytest/user/1

結果:

{
  "_index": "mytest",
  "_type": "user",
  "_id": "1",
  "_version": 2,
  "found": true,
  "_source": {
    "name": "xj",
    "age": 21,
    "sex": 0,
    "car": "奧迪a6l"
  }
}

說明:實際上Kibana也是通過restful請求的,其中url在配置文件中配置了。

2. Elasticsearch倒排索引原理

全文檢索底層采用倒排索引。

倒排索引比數據庫中的B-tree樹查詢效率快。

分析倒排索引:

正排索引是從文檔到關鍵字的映射(已知文檔求關鍵字),倒排索引是從關鍵字到文檔的映射(已知關鍵字求文檔)。

文檔內容:

序號

文檔內容

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:唯一標識

單詞:出現次數較多的單詞,提取出來,存儲在一個詞庫中。

倒排列表:存儲包含對應單詞的文檔的id

3. Elasticsearch高級查詢(重點)

3.1 數據插入:POST、PUT

# POST 插入數據,可以不加id

POST /mytest/user/
{
  "name": "xj_2",
  "age": 21,
  "sex": 0,
  "car": "奧迪a6l"
}

# 結果:
{
  "_index": "mytest",
  "_type": "user",
  "_id": "cycedXwBx9h5nuD8Z6Xh",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 2
}

說明:POST生成的id是ES自動生成的不重復標志

# PUT 插入數據,必須加id

PUT /mytest/user/1
{
  "name": "xj",
  "age": 21,
  "sex": 0,
  "car": "奧迪a6l"
}
# 結果:
{
  "_index": "mytest",
  "_type": "user",
  "_id": "1",
  "_version": 3,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 2
}

3.2 數據查詢:GET

### 簡單查詢

# 根據id進行查詢
GET /mytest/user/1
# 查當前索引下所有數據
GET /mytest/user/_search
# 查當前索引下多個id的數據
GET /mytest/user/_mget
{
  "ids": ["1","2"]
}

### 復雜查詢

# 查詢年齡age為21
GET /mytest/user/_search?q=age:21
# 查詢年齡age為30歲到60歲之間
GET /mytest/user/_search?q=age[30 TO 60]&sort=age:desc
# 查詢年齡age為30歲到60歲之間&倒序排列
GET /mytest/user/_search?q=age[20 TO 60]&sort=age:desc
# 查詢年齡age為30歲到60歲之間&倒序排列&分頁顯示前2條
GET /mytest/user/_search?sort=age:desc&size=2
# 查詢年齡age為30歲到60歲之間&倒序排列&分頁顯示:從第3條開始查2條
GET /mytest/user/_search?sort=age:desc&from=2&size=2

3.3 DSL語言查詢與過濾

3.3.1 什么是DSL語言

1、ES中的查詢請求有兩種方式:

    (1)簡易版的查詢

    (2)使用JSON完整的請求體,叫做結構化查詢(DSL)

2、由於DSL查詢更為直觀也更為簡易,所以大都使用這種方式。

3、DSL查詢是POST過去一個JSON,由於POST的請求是JSON格式的,所以存在很多靈活性,也有很多形式。

3.3.2 具體查詢示例

1term查詢:精確匹配,不會做分詞匹配

GET mytest/user/_search
{
  "query": {
    "term": {
      "name": "xy"
    }
  }
}

2match查詢:模糊查詢,支持分詞查詢,對match對象里邊的字段分詞查詢

說明:下邊示例是對car字段分詞查詢,可以查單個漢字,但不可以查單個字母

GET mytest/user/_search
{
  "query": {
    "match": {
      "car": "奧迪"
    }
  }
}
GET mytest/user/_search
{
  "query": {
    "match": {
      "car": "奧迪a4l"
    }
  }
}
GET mytest/user/_search
{
  "query": {
    "match": {
      "car": "a4l"
    }
  }
}

3、分頁:from起始位置,size記錄條數

說明:from=0為第一條數據

GET mytest/user/_search
{
  "from": 0,
  "size": 2,
  "query": {
    "match": {
      "car": "奧迪"
    }
  }
}

4、使用filter過濾年齡

說明:

(1)過濾年齡大於等於21歲小於等於50歲

(2)_source字段用於設置查詢結果顯示那幾個字段

GET /mytest/user/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 21,
            "lte": 50
          }
        }
      }
    }
  },
  "from": 0,
  "size": 3,
  "_source": ["name", "age"]
}

# 結果
{
  "took": 17,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 6,
    "max_score": 1,
    "hits": [
      {
        "_index": "mytest",
        "_type": "user",
        "_id": "5",
        "_score": 1,
        "_source": {
          "name": "xm",
          "age": 48
        }
      },
      {
        "_index": "mytest",
        "_type": "user",
        "_id": "cycedXwBx9h5nuD8Z6Xh",
        "_score": 1,
        "_source": {
          "name": "xj_2",
          "age": 21
        }
      },
      {
        "_index": "mytest",
        "_type": "user",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "xh",
          "age": 21
        }
      }
    ]
  }
}

4. ElasticsearchIK分詞器原理(重點)

4.1 傳統分詞器原理

默認分詞器:文字按單個字為一個單詞,英文可以以一個單詞為單詞

http://192.168.170.128: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
        }
    ]
}

5. ElasticsearchIK中文分詞器

5.1 為什么中文分詞器

因為Elasticsearch中默認的標准分詞器對中文分詞不是很友好,會將中文詞語拆分成一個一個中文的漢字作為單詞。因此引入中文分詞器elasticsearch-analysis-ik插件

5.2 中文分詞器下載安裝

5.2.1 下載地址

https://github.com/medcl/elasticsearch-analysis-ik/releases

注意:es-ik分詞插件的版本一定要和es安裝的版本對應。

5.2.2 安裝步驟

(1)將下載es的IK插件,解壓並重命名為ik

(2)上傳到/usr/local/elasticsearch-6.4.3/plugins/

(3)重啟elasticsearch

檢查安裝結果:

6. IK自定義中文詞典熱詞

步驟:

1、打開ik配置文件目錄:cd /usr/local/elasticsearch-6.4.3/plugins/ik/config/

2、新建文件:touch custom/new_word.dic

3、添加分詞:vi custom/new_word.dic

王者榮耀

一帶一路

4、修改配置文件:vi IKAnalyzer.cfg.xml

5、重啟elasticsearch

在重啟日志中可以看到加載了new_word.dic

6、測試

 

 

7. Elasticsearch Mapping映射

7.1 文檔映射的概念

已經把ElasticSearch的核心概念和關系數據庫做了一個對比,索引(index)相當於數據庫類型(type)相當於數據表映射(Mapping)相當於數據表的表結構。ElasticSearch中的映射(Mapping)用來定義一個文檔,可以定義所包含的字段以及字段的類型、分詞器及屬性等等。

文檔映射就是給文檔中的字段指定字段類型、分詞器。

使用GET /mymayikt/user/_mapping

7.2 映射的分類

7.2.1 動態映射

我們知道,在關系數據庫中,需要事先創建數據庫,然后在該數據庫實例下創建數據表,然后才能在該數據表中插入數據。而ElasticSearch中不需要事先定義映射(Mapping),文檔寫入ElasticSearch時,會根據文檔字段自動識別類型,這種機制稱之為動態映射。

7.2.1 靜態映射

在ElasticSearch中也可以事先定義好映射,包含文檔的各個字段及其類型等,這種方式稱之為靜態映射。

自動映射類型:

PUT /mytest/user/1
{
  "name": "xj",
  "age": 21,
  "sex": 0,
  "car": "奧迪a6l"
}

文檔映射:

命令:

# 文檔映射
POST /mytest/_mapping/user
{
  "user": {
    "properties": {
      "age": {
        "type": "integer"
      },
      "sex": {
        "type": "integer"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_smart",
        "search_analyzer": "ik_smart"
      },
      "car": {
        "type": "keyword"
      }
    }
  }
}

報錯:不能給已經創建好並且有內容的索引添加映射類型。

新建一個索引,再設置映射:

# 創建文檔
PUT /mytest_1
# 文檔映射
POST /mytest_1/_mapping/user
{
  "user": {
    "properties": {
      "age": {
        "type": "integer"
      },
      "sex": {
        "type": "integer"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_smart",
        "search_analyzer": "ik_smart"
      },
      "car": {
        "type": "keyword"
      }
    }
  }
}

# 插入數據
PUT /mytest_1/user/1
{
  "name": "xj",
  "age": 21,
  "sex": 0,
  "car": "奧迪a6l"
}
PUT /mytest_1/user/2
{
  "name": "xh",
  "age": 21,
  "sex": 1,
  "car": "保時捷911"
}
# 通過模糊查詢查“奧迪”,查不到,因為car類型為keyword
GET /mytest_1/user/_search
{
  "query": {
    "match": {
      "car": "奧迪"
    }
  }
}

# 修改文檔映射類型(不可以直接修改,先刪除索引再重新創建)
DELETE /mytest_1
PUT /mytest_1
POST /mytest_1/_mapping/user
{
  "user": {
    "properties": {
      "age": {
        "type": "integer"
      },
      "sex": {
        "type": "integer"
      },
      "name": {
        "type": "text",
        "analyzer": "ik_smart",
        "search_analyzer": "ik_smart"
      },
      "car": {
        "type": "text",
        "analyzer": "ik_smart"
      }
    }
  }
}

# 插入數據
PUT /mytest_1/user/1
{
  "name": "xj",
  "age": 21,
  "sex": 0,
  "car": "奧迪a6l"
}
PUT /mytest_1/user/2
{
  "name": "xh",
  "age": 21,
  "sex": 1,
  "car": "保時捷911"
}
PUT /mytest_1/user/3
{
  "name": "xx",
  "age": 23,
  "sex": 0,
  "car": "奧迪a4l"
}

# 再次通過模糊查詢查“奧迪”,能查到2條,因為car類型改為了text
GET /mytest_1/user/_search
{
  "query": {
    "match": {
      "car": "奧迪"
    }
  }
}

7.3 ES支持的數據類型

7.3.1 基本類型

字符串:string,string類型包含 text 和 keyword。

text:該類型被用來索引長文本,在創建索引前會將這些文本進行分詞,轉化為詞的組合,建立索引;允許es來檢索這些詞,text類型不能用來排序和聚合。

keyword:該類型不需要進行分詞,可以被用來檢索過濾、排序和聚合,keyword類型自讀那只能用本身來進行檢索(不可用text分詞后的模糊檢索)。

注意: keyword類型不能分詞,Text類型可以分詞查詢

數值型:long、integer、short、byte、double、float

日期型:date

布爾型:boolean

二進制型:binary

數組類型(Array datatype)

7.3.2 復雜類型

地理位置類型(Geo datatypes

地理坐標類型(Geo-point datatype):geo_point 用於經緯度坐標

地理形狀類型(Geo-Shape datatype):geo_shape 用於類似於多邊形的復雜形狀

7.3.3 特定類型(Specialised datatypes)

Pv4 類型(IPv4 datatype):ip 用於IPv4 地址

Completion 類型(Completion datatype):completion 提供自動補全建議

Token count 類型(Token count datatype):token_count 用於統計做子標記的字段的index數目,該值會一直增加,不會因為過濾條件而減少

mapper-murmur3 類型:通過插件,可以通過_murmur3_來計算index的哈希值

附加類型(Attachment datatype):采用mapper-attachments插件,可支持_attachments_索引,例如 Microsoft office 格式,Open Documnet 格式, ePub,HTML等

 

 Analyzer 索引分詞器,索引創建的時候使用的分詞器 比如ik_smart

Search_analyzer 搜索字段的值時,指定的分詞器

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM