前言
這篇文章詳細介紹了如何創建索引和某個類型的映射。
下文中[address]指代elasticsearch服務器訪問地址(http://localhost:9200)。
1 創建索引
1.1 簡單創建語句
curl -XPUT [address]/blog
1.2 帶參數的創建語句
curl -XPUT [address]/blog/ -d '{
"settings":{
"number_of_shards":1, //設置分片數量
"number_of_replicas":2, //設置副本數量
//自定義索引默認分析器
"index":{
"analysis":{
"analyzer":{
"default":{
"tokenizer":"standard", //分詞器
"filter":[ //過濾器
"asciifolding",
"lowercase",
"ourEnglishFilter"
]
}
},
"filter":{
"ourEnglishFilter":{
"type":"kstem"
}
}
}
}
}
}'
2 創建映射(扁平結構)
2.1 簡單創建語句
curl -XPUT [address]/blog/_mapping/article?pretty -d '{
"properties":{
"id":{"type":"long"},
"name":{"type":"string"},
"published":{"type":"date"}
}
}'
2.2 帶參數的創建語句
curl -XPUT [address]/blog/_mapping/article?pretty -d '{
"dynamic":"false", //關閉自動添加字段,關閉后索引數據中如果有多余字段不會修改mapping,默認true
"_id":{"index":"not_analyzed","store":"no"}, //設置文檔標識符可以被索引,默認不能被索引。可以設置為"_id":{"path":"book_id"},這樣將使用字段book_id作為標識符
"_all":{"enabled":"false"}, //禁用_all字段,_all字段包含了索引中所有其他字段的所有數據,便於搜索。默認啟用
"_source":{"enabled":"false"}, //禁用_source字段,_source字段在生成索引過程中存儲發送到elasticsearch的原始json文檔。elasticsearch部分功能依賴此字段(如局部更新功能),因此建議開啟。默認啟用
"_index":{"enabled":"true"}, //啟用_index字段,index字段返回文檔所在的索引名稱。默認關閉。
"_timestamp":{"enabled":"true","index":"not_analyzed","store":"true","format":"YYYY-mm-dd"}, //啟用時間戳並設置。時間戳記錄文檔索引時間,使用局部文檔更新功能時,時間戳也會被更新。默認未經分析編入索引但不保存。
"_ttl":{"enabled":"true","default":"30d"}, //定義文檔的生命周期,周期結束后文檔會自動刪除。
"_routing":{"required":"true","path":"name"} //指定將name字段作為路由,且每個文檔必須指定name字段。
"properties":{
"id":{
"type":"long",
//公共屬性
"store":"yes",
//數值特有屬性
"precision_step":"0" //指定為該字段生成的詞條數,值越低,產生的詞條數越多,查詢會更快,但索引會更大。默認4
},
"name":{
"type":"string",
//公共屬性
"store":"yes",
"index":"not_analyzed", //analyzed:編入索引供搜索、no:不編入索引、not_analyzed(string專有):不經分析編入索引
"boost":"1", //文檔中該字段的重要性,值越大表示越重要,默認1
"null_value":"jim", //當索引文檔的此字段為空時填充的默認值,默認忽略該字段
"include_in_all":"xxx" //此屬性是否包含在_all字段中,默認為包含
//字符串特有屬性
"analyzer":"xxx", //定義用於索引和搜索的分析器名稱,默認為全局定義的分析器名稱。可以開箱即用的分析器:standard,simple,whitespace,stop,keyword,pattern,language,snowball
"index_analyzer":"xxx", //定義用於建立索引的分析器名稱
"search_analyzer":"xxx", //定義用於搜索時分析該字段的分析器名稱
"ignore_above":"xxx" //定義字段中字符的最大值,字段的長度高於指定值時,分析器會將其忽略
},
"published":{
"type":"date",
//公共屬性
"store":"yes",
//日期特有屬性
"precision_step":"0", //指定為該字段生成的詞條數,值越低,產生的詞條數越多,查詢會更快,但索引會更大。默認4
"format":"YYYY-mm-dd" //指定日期格式,默認為dateOptionalTime
}
}
}'
3 創建映射(非扁平結構)
在第二章我們講解了創建映射的語句。所創建的是簡單的扁平結構映射。這一章我們看看如何創建非扁平結構映射。
3.1 樹形結構
樹形結構的作用是為索引層級路徑提供便利。例如一家汽車店中可能會有如下路徑:/cars/passenger/sport、/cars/passenger/camper、/cars/delivery_truck,我們想在搜索cars的時候返回三條記錄,搜索cars/passenger的時候返回前兩條記錄,可以這樣建立映射:
curl -XPUT [address]/path -d '{
"settings":{
//定義一個路徑分析器
"index":{
"analysis":{
"analyzer":{
"path_analyzer":{"tokenizer":"path_hierarchy"}
}
}
}
},
"mappings":{
"category":{
"properties":{
"category":{
"type":"string",
"fields":{
//定義多字段對象,使用category.path進行查詢時將啟用路徑分析匹配指定路徑下的所有文檔,使用category.name進行查詢時將精確匹配指定路徑的文檔,略過結構更深的文檔。
"name":{"type":"string","index":"not_analyzed"},
"path":{"type":"string","analyzer":"path_analyzer","store":true}
}
}
}
}
}
}'
3.2 對象
先執行curl –XPUT [address]/extend_mapping,創建extend_mapping索引
創建一個帶有對象屬性author的類型book:
curl –XPUT [address]/extend_mapping/_mapping/book –d ‘{
"properties":{
"title":{"type":"string","index":"not_analyzed"},
"author":{
"type":"object",
"properties":{
"firstName":{"type":"string","index":"not_analyzed"},
"lastName":{"type":"string","index":"not_analyzed"}
}
}
}
}’
3.3 嵌套對象
嵌套對象允許我們連接一個主文檔和多個附屬文檔,下面通過一個例子來說明嵌套對象的應用場景。
現在我們有一個服裝店,需要設計一個數據結構來存儲服裝店里的服裝信息。例如現在有一種名字為”cloth”的服裝,這件服裝現有兩件存貨,一件XXL的紅色和一件XL的黑色,請設計一個數據結構來存儲該服裝信息。
我們可能會把數據結構設計成這樣:
{
“name”:”cloth”,
“variation”:[
{“size”:”XXL”,”color”:”red”},
{“size”:”XL”,”color”:”black”}
]
}
直觀的來看,這個數據結構是能夠表現我們所描述的服裝信息的,我們依據這個結構創建以下映射(發送rest請求語句略):
{
"properties":{
"name":{"type":"string","index":"not_analyzed"},
"variation":{
"properties":{
"size":{"type":"string","index":"not_analyzed"},
"color":{"type":"string","index":"not_analyzed"}
}
}
}
}
建立映射后索引以下數據:
{
"name": "cloth",
"variation": [
{
"size": "XXL",
"color": "red"
},
{
"size": "XL",
"color": "black"
}
]
}
下面我們查詢一下我們的服裝信息庫,看看是否有尺寸為XXL,顏色為black的服裝:
{
"filter": {
"and": [
{
"term": {
"variation.size": "XXL"
}
},
{
"term": {
"variation.color": "black"
}
}
]
}
}
出乎意料的是,該查詢返回了結果:
{
......(此處信息略去)
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "extend_mapping",
"_type": "unnested_cloth",
"_id": "AVACnlA-8eAUpvGq_eZa",
"_score": 1,
"_source": {
"name": "cloth",
"variation": [
{
"size": "XXL",
"color": "red"
},
{
"size": "XL",
"color": "black"
}
]
}
}
]
}
}
這與我們的預期不符,我們只有XXL紅色和XL黑色兩件服裝,並沒有所查詢的XXL黑色服裝。
這是因為按照我們之前定義的映射結構,尺寸信息(“size”:”XXL”,”size”:”XL”)和顏色信息(“color”:”red”,”color”:”black”)都存在同一個文檔中,ES無法將XXL和red、XL和black綁定在一起,因此在查詢時造成了混淆。
解決的方法就是使用嵌套對象,將variation對象的類型指定為嵌套:
重新創建以下映射:
{
"properties":{
"name":{"type":"string","index":"not_analyzed"},
"variation":{
“type”:”nested”,
"properties":{
"size":{"type":"string","index":"not_analyzed"},
"color":{"type":"string","index":"not_analyzed"}
}
}
}
}
索引之前的測試數據:
{
"name": "cloth",
"variation": [
{
"size": "XXL",
"color": "red"
},
{
"size": "XL",
"color": "black"
}
]
}
現在我們通過”type”:”nested”將variation對象指定為嵌套對象,需要注意的是,如果我們對新映射執行類似之前的查詢,將無任何文檔返回。因為對於嵌套映射,必須要使用專用的查詢語法,如下:
{
"filter": {
"nested": {
"path": "variation",
"filter": {
"and": [
{
"term": {
"variation.size": "XXL"
}
},
{
"term": {
"variation.color": "black"
}
}
]
}
}
}
}
這次的查詢如我們的預期,沒有返回結果。這是因為使用嵌套結構后,當我們索引測試數據時,事實上ES生成了3個文檔,一個cloth的主文檔,和兩個variation對象的附屬文檔,這樣就分離存儲了兩件服裝存貨,避免了尺寸和顏色的混淆。
