是什麼?html
Elasticsearch是一個基於Apache Lucene(TM)的開源搜索引擎。不管在開源仍是專有領域,Lucene能夠被認爲是迄今爲止最早進、性能最好的、功能最全的搜索引擎庫。正則表達式
Elasticsearch不只僅是Lucene和全文搜索,咱們還能這樣去描述它:數據庫
面向文檔apache
應用中的對象不多隻是簡單的鍵值列表,更多時候它擁有複雜的數據結構,好比包含日期、地理位置、另外一個對象或者數組。json
總有一天你會想到把這些對象存儲到數據庫中。將這些數據保存到由行和列組成的關係數據庫中,就好像是把一個豐富,信息表現力強的對象拆散了放入一個很是大的表格中:你不得不拆散對象以適應表模式(一般一列表示一個字段),而後又不得不在查詢的時候重建它們。數組
Elasticsearch是面向文檔(document oriented)的,這意味着它能夠存儲整個對象或文檔(document)。然而它不只僅是存儲,還會索引(index)每一個文檔的內容使之能夠被搜索。在Elasticsearch中,你能夠對文檔(而非成行成列的數據)進行索引、搜索、排序、過濾。這種理解數據的方式與以往徹底不一樣,這也是Elasticsearch可以執行復雜的全文搜索的緣由之一。服務器
使用案例:數據結構
可是Elasticsearch並不僅是面向大型企業的,它還幫助了不少相似DataDog以及Klout的創業公司進行了功能的擴展。app
Elasticsearch 與 Solr 的比較總結elasticsearch
Solr 是傳統搜索應用的有力解決方案,但 Elasticsearch 更適用於新興的實時搜索應用。
index、type
在Elasticsearch中,文檔歸屬於一種類型(type),而這些類型存在於索引(index)中,咱們能夠畫一些簡單的對比圖來類比傳統關係型數據庫:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集羣能夠包含多個索引(indices)(數據庫),每個索引能夠包含多個類型(types)(表),每個類型包含多個文檔(documents)(行),而後每一個文檔包含多個字段(Fields)(列)。
什麼是mapping
ES的mapping很是相似於靜態語言中的數據類型:聲明一個變量爲int類型的變量, 之後這個變量都只能存儲int類型的數據。一樣的, 一個number類型的mapping字段只能存儲number類型的數據。
同語言的數據類型相比,mapping還有一些其餘的含義,mapping不只告訴ES一個field中是什麼類型的值, 它還告訴ES如何索引數據以及數據是否能被搜索到。
當你的查詢沒有返回相應的數據, 你的mapping頗有可能有問題。當你拿不許的時候, 直接檢查你的mapping。
剖析mapping
一個mapping由一個或多個analyzer組成, 一個analyzer又由一個或多個filter組成的。當ES索引文檔的時候,它把字段中的內容傳遞給相應的analyzer,analyzer再傳遞給各自的filters。
filter的功能很容易理解:一個filter就是一個轉換數據的方法, 輸入一個字符串,這個方法返回另外一個字符串,好比一個將字符串轉爲小寫的方法就是一個filter很好的例子。
一個analyzer由一組順序排列的filter組成,執行分析的過程就是按順序一個filter一個filter依次調用, ES存儲和索引最後獲得的結果。
總結來講, mapping的做用就是執行一系列的指令將輸入的數據轉成可搜索的索引項。
默認analyzer
回到咱們的例子, ES猜想description字段是string類型,因而默認建立一個string類型的mapping,它使用默認的全局analyzer, 默認的analyzer是標準analyzer。
咱們能夠在作查詢的時候鍵入_analyze關鍵字查看分析的過程。使用如下指令查看description字段的轉換過程:
能夠看到, 咱們的description字段的值轉換成了[pretty], [cool], [guy], 在轉換過程當中大寫的A, 標點符號都被filter過濾掉了, Pretty也轉成了全小寫的pretty,
這裏比較重要的是, 即便ES存儲數據的時候仍然存儲的是完整的數據, 可是能夠搜索到這條數據的關鍵字只剩下這三個單詞了, 其餘的都是拋棄掉了。
如今就能獲得正確的結果,這是一個公認的簡單例子, 可是它描述了ES是如何工做的, 不要把mapping想成是數據類型, 把它想象成是搜索數據的指令集合。若是你不想字符"a"被刪除, 你須要修改你的analyzer。
mapping配置
能夠修改的項:
不容許修改的項:
注意的是新增字段或更改分析器以後,須要再次對全部文檔進行索引重建
字段的數據類型
簡單類型
有層級結構的類型
好比object 或者 nested.
特殊類型
好比geo_point, geo_shape, or completion.
動態模板:
使用dynamic_templates能夠徹底控制新字段的映射,你設置能夠經過字段名或數據類型應用一個徹底不一樣的映射。
例子:咱們爲/my_index/my_type 分別建立
es:字段名以_es結尾的且是string類型的,須要使用spanish分詞器
enn:其餘字段的且是string類型的,須要使用english分詞器
PUT /my_index
{ "mappings": { "my_type": { "dynamic_templates": [ { "es": { =>模板名稱,隨意,通常要有語義"match": "*_es", =>匹配字段名稱"match_mapping_type": "string"=>匹配字段類型"mapping": { =>當匹配到以後,該字段的具體設置"type": "string", "anaylzer": "spanish" } } }, { "en": { =>模板名稱,隨意,通常要有語義"match": "*", =>匹配字段名稱(任意,通用的順序要在以後)"match_mapping_type": "string"=>匹配字段類型"mapping": { =>當匹配到以後,該字段的具體設置"type": "string", "anaylzer": "english" } } } ] } } }
index別名設置
一個別名可以指向多個索引,所以當咱們將別名指向新的索引時,咱們還須要刪除別名原來到舊索引的指向。這個改變須要是原子的,即意味着咱們須要使用_aliases端點:
POST /_aliases { "actions": [ { "remove": { "index": "my_index_v1", "alias": "my_index" }}, { "add": { "index": "my_index_v2", "alias": "my_index" }} ] }
如今你的應用就在零停機時間的前提下,實現了舊索引到新索引的透明切換。
問題:
一、全文索引(json全文爬數據)
二、聚合沒法根據匹配度排序
三、聚合沒法真分頁
一個mapping示例
{ "dynamic": "false", "dynamic_templates": [ { "indexes": { "mapping": { "type": "string", "fields": { "raw": { "index": "not_analyzed", "null_value": "", "type": "string" } } }, "match_mapping_type": "string", "path_match": "indexes.*" } } ], "properties": { "indexes": { "dynamic": "strict", "properties": { "application": { "type": "string", "index": "not_analyzed" }, "attribute_name": { "type": "string", "fields": { "raw": { "type": "string", "index": "not_analyzed", "null_value": "" } } }, "category": { "type": "string", "index": "not_analyzed" }, "create_time": { "type": "long" }, "data_md5": { "type": "string", "index": "not_analyzed" }, "disable": { "type": "boolean" }, "keyword": { "type": "string", "fields": { "raw": { "type": "string", "index": "not_analyzed", "null_value": "" } } }, "project_code": { "type": "string", "fields": { "raw": { "type": "string", "index": "not_analyzed", "null_value": "" } } }, "project_id": { "type": "string", "index": "not_analyzed" }, "project_title": { "type": "string", "fields": { "raw": { "type": "string", "index": "not_analyzed", "null_value": "" } } }, "project_type": { "type": "string", "index": "not_analyzed", "fields": { "raw": { "type": "string", "index": "not_analyzed", "null_value": "" } } }, "reference_count": { "type": "long" }, "tenant": { "type": "long" }, "top_reference_count": { "type": "long" }, "type": { "type": "long" }, "update_time": { "type": "long" }, "user_id": { "type": "long" }, "user_name": { "type": "string", "fields": { "raw": { "type": "string", "index": "not_analyzed", "null_value": "" } } } } }, "tenant": { "type": "long" } } }
{ "query": { "bool": { "must": [ { "match_all": {} } ] } }, "from": 0, "size": 1 }
{ "query": { "bool": { "must": [ { "match_all": {} } ] } }, "from": 0, "size": 0, "aggregations": { "mid": { "aggregations": { "terminal": { "terms": { "field": "terminal", "size": 0 } } }, "terms": { "field": "mid", "size": "1" } } } }
{ "query": { "bool": { "must": [ { "match_all": {} } ] } }, "from": 0, "size": 0, "aggregations": { "COUNT(distinct (mid))": { "cardinality": { "field": "(mid)" } } } }
{ "query" : { "query_string" : {"query" : "name:rcx"} } }
{ "query": { "match": { "title": "crime and punishment" } } }
{ "query": { "wildcard": { "title": "cr?me" } } }
{ "query": { "range": { "year": { "gte" :1890, "lte":1900 } } } }
{ "query": { "regexp": { "title": { "value" :"cr.m[ae]", "boost":10.0 } } } }
{ "query": { "bool": { "must": { "term": { "title": "crime" } }, "should": { "range": { "year": { "from": 1900, "to": 2000 } } }, "must_not": { "term": { "otitle": "nothing" } } } } }