轉載請注明出處
ElasticSearch
es 版本1.0x 、2.0x、5.0x 版本直接從2.0跳到5.0是為了統一elk所有版本
6版本之前 索引的type可以為多個,6版本的一個索引type只能有一個,7去除type。因為對於es來說type管理是多余了,直接通過索引管理一類數據即可
文檔:
動態更新索引 : https://www.elastic.co/guide/cn/elasticsearch/guide/current/dynamic-indices.html#img-index-segments 主要正對索引數據內存優化講解
近實時搜索 : https://www.elastic.co/guide/cn/elasticsearch/guide/current/near-real-time.html 主要正對索引數據內存優化講解
查詢中緩存使用 : https://www.elastic.co/guide/cn/elasticsearch/guide/current/filter-caching.html
安裝
Elasticsearch
不可用root用戶操作,必須使用普通用戶,且下載解壓的所有文件所屬用戶為普通用戶;
elasticsearch 創建搜索時默認創建5個分片,一個備份
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.zip
- 解壓、安裝
unzip elasticsearch-6.3.2.zip
cd elasticsearch-6.3.2
bin/elasticsearch
org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root。
解決方案:不可用root操作,切換普通用戶chown 普通用戶:普通用戶組 elasticsearch-6.3.2 -R 再bin/elasticsearch
-
配置
- 修改elasticsearch.yml,增加跨域的配置(需要重啟es才能生效)
http.cors.enabled: true http.cors.allow-origin: "*"
-
cluster.name: 集群名【如果使用集群,多個節點這個屬性需要一直】
-
node.name : 節點名【如果使用集群,多個節點這個屬性需要全部不同】
-
node.master:是否為master (集群使用)【如果使用集群,Master節點此處為true,Slave節點此處為false】
-
network.host:綁定iP
-
discovery.zen.ping.unicast.hosts:["集群MasterIP"] 找到master主機iP,【集群salve節點必須設置,master節點不需要設置】
-
驗證
curl http://localhost:9200
安裝中ERROR
- max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536].
原因:這個問題比較常見,原因是因為最大虛擬內存太小
解決方案:切換到root用戶,編輯limits.conf配置文件,運行:vi /etc/security/limits.conf添加如下內容(備注:* 代表Linux所有用戶名稱(比如 hadoop)保存、退出、重新登錄才可生效。):
* soft nofile 131072
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
- max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144].
原因:無法創建本地文件問題,用戶最大可創建文件數太小
解決方案:切換到root用戶下,修改配置文件sysctl.conf,vi /etc/sysctl.conf添加下面配置: vm.max_map_count=655360,並執行命令:sysctl -p,然后重新啟動Elasticsearch,即可啟動成功。
vm.max_map_count=655360
-
elasticsearch 啟動時需要非root用戶
報錯:(Permission denied) java.io.FileNotFoundException: /srv/elasticsearch/logs/test-es-cluster.log (Permission denied)
需要給/srv/elasticsearch 目錄es用戶權限 chown elastic:elastic -R /src/elasticsearch
認證插件 x-pack安裝
- 使用es用戶進入elastic search/bin 執行
elastixcsearch-plugin install x-pack
elasticsearch plugin Connection refused (Connection refused) 可能是下載插件連接錯誤,需要代理
-
直接下載
https://www.elastic.co/guide/en/x-pack/current/index.html
-
將對應版本的x-pack.zip放入elasticsearch 所在的服務器上
-
elasticsearch-plugin install file:///opt/x-pack.zip
注意路徑前面加file:// 然后安裝提示完成安裝 -
bin/x-pack/setup-passwords auto
生成默認密碼 -
或
bin/x-pack/setup-passwords interactive
生成指定密碼 如下
三個內置用戶名 和秘密
[elastic@test-tars-elasticsearch-91-59-pbs-sh x-pack]$ ./setup-passwords interactive
Initiating the setup of passwords for reserved users elastic,kibana,logstash_system.
You will be prompted to enter passwords as the process progresses.
Please confirm that you would like to continue [y/N]y
Enter password for [elastic]:
Reenter password for [elastic]:
Enter password for [kibana]:
Reenter password for [kibana]:
Enter password for [logstash_system]:
Reenter password for [logstash_system]:
Changed password for user [kibana]
Changed password for user [logstash_system]
Changed password for user [elastic]
[elastic@test-tars-elasticsearch-91-59-pbs-sh x-pack]$
Elasticsearch-head
安裝npm
$ curl -sL -o /etc/yum.repos.d/khara-nodejs.repo https://copr.fedoraproject.org/coprs/khara/nodejs/repo/epel-7/khara-nodejs-epel-7.repo
$ yum install -y nodejs nodejs-npm
-
修改npm 鏡像源,下載安裝超快:
npm config set registry https://registry.npm.taobao.org npm info underscore
-
安裝 grunt
npm install -g grunt-cli
npm install grunt
-
驗證
grunt server
ERROR: [root@localhost elasticsearch-head]# >> Local Npm module "grunt-contrib-clean" not found. Is it installed? >> Local Npm module "grunt-contrib-concat" not found. Is it installed? >> Local Npm module "grunt-contrib-watch" not found. Is it installed? >> Local Npm module "grunt-contrib-connect" not found. Is it installed? >> Local Npm module "grunt-contrib-copy" not found. Is it installed? >> Local Npm module "grunt-contrib-jasmine" not found. Is it installed? Warning: Task "connect:server" not found. Use --force to continue.
解決:
npm install grunt-contrib-clean
npm install grunt-contrib-concat
依次安裝缺少的依賴,完成;
安裝Elasticsearch-head
elasticsearch-head是個用來與Elasticsearch互動的圖形化界面插件,有了他你可以很方便的管理你的Elasticsearch,查看你的Elasticsearch狀態或者測試你的查詢語句。這個是他官方的
GitHub頁面
。
- 安裝(使用root用戶) 下載去githut搜索elasticsearch-head 選擇mobz開頭的
git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
//速度較慢,就是用國內鏡像 npm install -g cnpm --registry=https://registry.npm.taobao.org
grunt server
WARN 警告可以暫忽略
- 修改配置: vim Gruntfile.js 添加hostname : '${ip}'
connect: {
server: {
options: {
hostname: '0.0.0.0',
port: 9100,
base: '.',
keepalive: true
}
}
}
- 安裝完成后用http://localhost:9100/ 打開即可。
安裝中ERROR
> grunt server
sh: grunt: 未找到命令
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! elasticsearch-head@0.0.0 start: `grunt server`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the elasticsearch-head@0.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2018-04-21T08_42_24_584Z-debug.log
解決方案:npm install -g grunt-cli
中文文檔:https://es.xiaoleilu.com/
安裝參考:https://www.marsshen.com/2018/04/23/Elasticsearch-install-and-set-up/
ES概念
我們首先要做的是存儲員工數據,每個文檔代表一個員工。在Elasticsearch中存儲數據的行為就叫做索引(indexing),不過在索引之前,我們需要明確數據應該存儲在哪里。
在Elasticsearch中,文檔歸屬於一種類型(type),而這些類型存在於索引(index)中,我們可以畫一些簡單的對比圖來類比傳統關系型數據庫:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
每一個index都有一個Mapping來定義該index怎樣去索引,需要注意的是,大體概念我們可以這樣理解ES中的index和Mapping Type,index 對應SQL DB中的database,Mapping Type對應 SQL DB中的table,但是又不完全一樣,因為在SQL DB中,不同table中的字段名稱可以重復,但是定義可以不一樣,再ES中卻不可以存在這種情況,因為ES是基於Lucene,在ES映射到Lucene時,同一個index下面的不同mapping的同一字段名映射是同一個的,也就意味着,再不同的mapping中,相同字段名的類型也要保持一致
分片:每個索引中分片,數據量大的時候分片利於查詢;
備份:索引的備份,備份也提供查詢功能;
elasticsearch-head概覽中方框中的123表示索引的分片 方框比較寬的表示主分片,其他的表示分片的備份,細方框的為對應數字粗方框的分片備份;
索引中_mappings中有字段結構表示結構索引,沒有則是非結構話索引;
elasticsearch 隱藏管理:分片機制(將數據分攤到不同的分片中)shard機制
elasticsearch 擴容方案:(現狀:6台服務器,每台1T,需要增長到8T容量)
垂直擴容:重新購買兩台服務器,每台服務器的容量時2T,替換掉老的兩套服務器;
水平擴容:新購兩台服務器,每台服務器1T,直接加入集群中;
all_field : elasticsearch在創建index的document時會將多個field串連起來成為一個all_field 全局索引搜索沒有指定某一個field搜索時會對這個all_field搜索
exact value :在建立倒排索引時,分詞時是將整個值一起作為一個關鍵詞建立索引;
full text: 在建立倒排索引時,會經歷各種處理,拆分詞 、同義詞轉換、大小寫轉換等;
keyword: keyword不會進行分詞
__倒排索引:__通過固定的分詞方式將文本分成許多不重復的詞條,然后標記每個詞條所出現的文檔;
https://www.elastic.co/guide/cn/elasticsearch/guide/current/inverted-index.html
分片/副本
分片:大量文檔時,可分為較小的分片,每個分片都是一個獨立的Apache Lucene索引;
- 更多分片使索引能傳到更多的服務器,可並行處理更多文件;
- 更多分片導致每個分片的資源量減少,處理效率提高;
- 更多分片會導致搜索是面臨更多問題,因為必須從更多分片中合並結果,使得查詢的聚合階段需要更多資源;
分片數 視情況而定,默認值是一個不錯的選擇;
副本:為提高查詢的吞吐量或實現高可用可以時用副本,副本是一個分片的精確復制
ES使用
關閉Elasticsearch
- Ctrl+c
- kill -9 進程號
- curl 請求關閉 : curl -XPOST http://localhost:9200/_cluster/nodes/_shutdown
- curl 關閉某一個nod : curl -XPOST http://localhost:9200/_cluster/nodes/節點標識符/_shutdown
創建索引:
PUT:http://ip:端口/索引(index)
{
"settings【關鍵詞】": {
"number_of_shards【關鍵詞】": "指定索引的分片數",
"number_of_replicas【關鍵詞】": "指定索引備份數"
},
"mappings【關鍵詞】": {
"類型名1(type)": {
"properties【關鍵詞】屬性定義集合": {
"屬性名1": {
"type【關鍵詞】類型值": "",
"analyzer【關鍵詞】(分詞設置)": ""
},
"屬性名2": {
"type【關鍵詞】類型值": ""
}
}
},
"類型名2(type)": {}
}
}
字段屬性詳細:
{
"name": {
"type": "string //類型",
"store": "yes //公共屬性 https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-store.html",
"index": "not_analyzed //analyzed:編入索引供搜索、no:不編入索引、not_analyzed(string專有):不經分析編入索引",
"boost": "1 //文檔中該字段的重要性,值越大表示越重要,默認1",
"null_value": "jim //當索引文檔的此字段為空時填充的默認值,默認忽略該字段",
"include_in_all": "xxx //此屬性是否包含在_all字段中,默認為包含",
"analyzer": "xxx//text特有屬性 定義用於索引和搜索的分析器名稱,默認為全局定義的分析器名稱。可以開箱即用的分析器:standard,simple,whitespace,stop,keyword,pattern,language,snowball",
"index_analyzer": "xxx //text特有屬性 定義用於建立索引的分析器名稱",
"search_analyzer": "xxx //text特有屬性 定義用於搜索時分析該字段的分析器名稱",
"ignore_above": "xxx //text特有屬性 定義字段中字符的最大值,字段的長度高於指定值時,分析器會將其忽略"
}
}
創建成功:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "user"
}
添加已存在的索引返回報錯:
{
"error": {
"root_cause": [
{
"type": "resource_already_exists_exception",
"reason": "index [user/7sQYbNEnS96DL2K-xi83YA] already exists",
"index_uuid": "7sQYbNEnS96DL2K-xi83YA",
"index": "user"
}
],
"type": "resource_already_exists_exception",
"reason": "index [user/7sQYbNEnS96DL2K-xi83YA] already exists",
"index_uuid": "7sQYbNEnS96DL2K-xi83YA",
"index": "user"
},
"status": 400
}
添加字段
PUT:http://ip:端口/索引(index)/類型(type)/_mapping
{
"properties": {
"newFieldName": {
"type": "string",
"index": "not_analyzed"
}
}
}
字段不存在或者添加的字段和索引中已經存在的字段結果相同則返回成功:
{
"acknowledged": true
}
索引中存在該字段,結構與提交的結構不同則會返回錯誤:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "mapper [newField] of different type, current_type [text], merged_type [integer]"
}
],
"type": "illegal_argument_exception",
"reason": "mapper [newField] of different type, current_type [text], merged_type [integer]"
},
"status": 400
}
插入數據
POST : http://ip:端口號/索引名(index)/類型名(type)/文檔id(不填es默認會創建)
如果指定ID的數據存在則會更新
{
"屬性名1": "屬性值",
"屬性名2": "屬性值"
}
成功返回:
添加成功 result值為"created",更新成功"updated"
{
"_index": "user",
"_type": "list",
"_id": "JqBA4GsBgfD8XS4-tiAw",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
修改數據
- post:
htpp://ip:端口號/索引名(index)/類型名(type)/文檔id/_update【關鍵詞】(指定操作)
在內部,Elasticsearch必須首先獲取文檔,從_source屬性獲取數據,刪除舊的文件,更改 _source 屬性,然后把它作為新的文檔來索引,因為信息一但在Lucene中倒排索引中存儲就不能再被修改,當並發是,嘗試寫入一個已經更改的文檔將會失敗,提示version error版本錯誤,這是elasticsearch中文檔的版本控制功能(樂觀鎖)
{
"doc【關鍵詞】": {
"屬性名1": "新的屬性值"
}
}
- post:
htpp://ip:端口號/索引名(index)/類型名(type)/文檔id/_update【關鍵詞】(指定操作)
{
"script【關鍵詞】(腳本的方式修改)": {
"lang【關鍵詞】(指定腳本語言)": " painless【關鍵詞】(es內置的腳本語言,es支持很多中腳本語言js.python等)",
"inline【關鍵詞】(指定腳本內容)": "ctx._source.age = params.數組key //方式2",
"params(修改的數組,在上面設置age的值時可以直接引用)": {
"數組key1": "數組的值value1",
"數組key2": "數組的值value2"
}
}
}
Script查詢(TODO)
https://www.elastic.co/guide/cn/elasticsearch/guide/current/script-score.html
補充script相關知識
修改成功:
修改成功result值為"updated" 修改數據無改變result值為"noop",successful為影響條數
{
"_index": "user",
"_type": "list",
"_id": "100",
"_version": 8,
"result": "updated",
"_shards": {
"total": 0,
"successful": 1,
"failed": 0
}
}
刪除文檔
delete:http://ip:端口/索引名(index)/類型名(type)/文檔id(直接delete方式請求即刪除)
成功返回:
刪除成功result值為"deleted" 刪除數據為空result值為"not_found"通過ID刪除successful都是1
{
"_index": "user",
"_type": "list",
"_id": "100",
"_version": 10,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 9,
"_primary_term": 1
}
刪除索引
delete: http://ip:端口/索引名(index)(直接delete方式請求即刪除)
成功返回
{
"acknowledged": true
}
不存在返回錯誤
{
"error": {
"root_cause": [
{
"type": "index_not_found_exception",
"reason": "no such index",
"resource.type": "index_or_alias",
"resource.id": "user",
"index_uuid": "_na_",
"index": "user"
}
],
"type": "index_not_found_exception",
"reason": "no such index",
"resource.type": "index_or_alias",
"resource.id": "user",
"index_uuid": "_na_",
"index": "user"
},
"status": 404
}
查詢數據
概念
結構化查詢(query DSL): 會計算每個文檔與查詢語句的相關性,會給出一個相關性評分 _score
,並且 按照相關性對匹配到的文檔進行排序。 這種評分方式非常適用於一個沒有完全配置結果的全文本搜索。查詢語句會詢問每個文檔的字段值與特定值的匹配程度如何?
結構化過濾(Filter DSL): 在結構化過濾中,我們得到的結果 總是 非是即否,要么存於集合之中,要么存在集合之外。結構化過濾不關心文件的相關度或評分;它簡單的對文檔包括或排除處理。執行速度非常快,不會計算相關度(直接跳過了整個評分階段)而且很容易被緩存。一條過濾語句會詢問每個文檔的字段值是否包含着特定值
簡單查詢
GET:http://ip:端口號/索引(index)/類型名(type)/文檔id(直接get請求即可查詢)
條件查詢
POST:http://ip:端口號/索引(index)/_search【關鍵詞】(指定查詢)
{
"from【關鍵詞】(從第幾條開始返回)": 1,
"size【關鍵詞】(返回多少條)": 1,
"sort【關鍵詞】(排序)": [
{
"屬性值": {
"order【關鍵詞】(代表排序)": "desc/asc(排序方式)"
}
}
],
"_source【關鍵字】(表示需要查的字段)": ["name","age"],
"query【關鍵詞】(指定條件查詢)": {
"match_all【關鍵詞】(//方式1:查詢所有的內容代表所有內容)": {},
"match【關鍵詞】(//方式2:關鍵詞查詢代表不是所有內容,有條件)": {
"屬性名": "屬性值"
}
}
}
查詢語法:
- query
說明:過濾語句集合
- filtered
說明:過濾器,已廢棄
- match_all
說明:查詢所有
{
"query": {
"match_all": {}
}
}
- bool
說明:復合過濾器,它可以接受多個其他過濾器作為參數,並將這些過濾器結合成各式各樣的布爾(邏輯)組合,
bool
過濾器本身仍然還只是一個過濾器。 這意味着我們可以將一個bool
過濾器置於其他bool
過濾器內部,
{
"query": {
"bool": {
"must": [
{
"term": {
"name": {
"value": "abc"
}
}
}
],
"must_not": [
{
"term": {
"age": {
"value": "12"
}
}
}
]
}
}
}
- filter
說明:過濾器,不進行評分或相關度的計算,所以所有的結果都會返回一個默認評分
1
{
"query": {
"bool": {
"filter": [
{
"match": {
"username": {
"query": "中交9",
"operator": "or"
}
}
},
{
"match": {
"nickname": {
"query": "1112",
"operator": "or"
}
}
}
]
}
}
}
- term
說明:精確查詢,在倒排索引中查詢,因為值被分詞在倒排索引中,所以也可以說包含,不會將傳遞的數據分詞,match會將傳遞的數據分詞
{
"query": {
"bool": {
"must": [
{
"term": {
"name": {
"value": "abc"
}
}
}
]
}
}
}
- terms
說明:在倒排索引中精確匹配多個數據,是
term
的復數版
{
"query": {
"bool": {
"must": [
{
"terms": {
"name": [
"aaa",
"bbb"
]
}
}
]
}
}
}
- constant_score
說明:查詢以非評分模式來執行。將一個不變的常量評分應用於所有匹配的文檔。它被經常用於你只需要執行一個 filter 而沒有其它查詢(例如,評分查詢)的情況下。
給每條記錄以一條固定的評分,即不計算相關度評分,所能constant_score只支持filter上下文
https://www.elastic.co/guide/cn/elasticsearch/guide/cn/combining-queries-together.html
{
"constant_score": {
"filter": {
"term": { "category": "ebooks" }
}
}
}
- must
說明:所有的語句都 必須(must) 匹配,與
AND
等價。
{
"query": {
"bool": {
"must": [
{
"match": {
"id": "100"
}
}
]
}
}
}
- must_not
說明:所有的語句都 不能(must not) 匹配,與
NOT
等價。
{
"query": {
"bool": {
"must_not": [
{
"match": {
"id": "100"
}
}
]
}
}
}
- should
說明:至少有一個語句要匹配,與
OR
等價。
{
"query": {
"bool": {
"should": [
{
"match": {
"id": "100"
}
}
]
}
}
}
- range
說明:范圍查詢
gt
:>
大於(greater than)
lt
:<
小於(less than)
gte
:>=
大於或等於(greater than or equal to)
lte
:<=
小於或等於(less than or equal to)
"range" : {
"price" : {
"gte" : 20,
"lte" : 40
}
}
查詢過去一小時內的
"range" : {
"timestamp" : {
"gt" : "now-1h"
}
}
日期計算還可以被應用到某個具體的時間,並非只能是一個像 now 這樣的占位符。只要在某個日期后加上一個雙管符號 (||
) 並緊跟一個日期數學表達式就能做到:早於 2014 年 1 月 1 日加 1 月(2014 年 2 月 1 日 零時)
"range" : {
"timestamp" : {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-01 00:00:00||+1M"
}
}
范圍查詢同樣可以處理字符串字段, 字符串范圍可采用 字典順序(lexicographically) 或字母順序(alphabetically)。例如,下面這些字符串是采用字典序(lexicographically)排序的:
5, 50, 6, B, C, a, ab, abb, abc, b
"range" : {
"title" : {
"gte" : "a",
"lt" : "b"
}
}
- exists
說明:查詢會返回那些在指定字段有任何值的文檔
POST station/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "fieldName"
}
}
]
}
}
}
返回指定字段不存在任何值的文檔
POST station/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "fieldName"
}
}
]
}
}
}
- match
說明:對搜索的字符串進行分詞,從目標字段中的倒序索引中查找是否有其中某個分詞.
參數有:
query:"" 查詢的數據
operator:"or" 默認"or"可不寫,表示query中的數據分詞后匹配中一個詞條則該文檔符合,"and"表示query中的數據分詞后需要全部匹配上的文檔才符合
minimum_should_match:2 表示query分詞后與文檔中至少匹配的詞條數量,當operator為and時設置minimum_should_match搜索結果為空
在6.x已經不支持在math里面使用type,之前加上"type":"pharse"功能和match_pharse相同
{
"query": {
"bool": {
"must": [
{
"match": {
"sku_name_string": {
"query": "你好 再見",
"operator": "or",
"minimum_should_match" : 2
}
}
}
]
}
}
}
- match_pharse
說明:先將搜索的內容拆詞,拆成詞條后,每個詞條與倒排索引中詞條匹配,同時匹配上所有搜索內容的詞條,並且順序一樣,則該文檔符合搜索
參數有:
query:"" 查詢的數據
analyzer:"whitespace" 將所有的內容以何中分詞方式分成詞條,然后與倒排索引中的詞條匹配
slop:2 slop參數告訴match_phrase查詢詞條能夠相隔多遠時仍然將文檔視為匹配。相隔多遠的意思是,你需要移動一個詞條多少次來讓查詢和文檔匹配?
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"sku_name_string": {
"query": "京VI",
"analyzer": "whitespace",
"slop" : 2
}
}
}
]
}
}
}
- multi_match
說明:用於匹配多個字段匹配同一個內容,搜索內容分詞后與倒排索引中多個字段匹配
參數有:
query:"" 查詢的數據
fields:["username","nickname"] 匹配的字段
type:"best_fields" 過濾篩選的類型,
"best_fields"只要任意匹配一個字段即可,使用最匹配的那個字段相關度評分;
"more_fields"只要匹配做任意一個字段,但會將匹配度的得分進行組合;
"corss_fields"使用相同的分詞器,只要有一個字段匹配即可;
"phrase"先將搜索內容以fields中字段的方式分詞,然后使用match_phrase方式與fields中每個字段匹配。對每個字段運行match_phrase查詢,並合並每個字段的權重
"phrase_prefix"最匹配的字段要完全匹配搜索的內容(包含搜索的內容),與phrase類似,觀察到在將搜索內容分詞的后面會有
*
號,原字段分詞方式為:username 空格分詞 nickname是一字一詞通過validate驗證得到explanation可分析搜索過程,"explanation": """+(+(username:"小明 小紅*" | nickname:"小 明 紅*")) #DocValuesFieldExistsQuery [field=_primary_term]"""
猜測可能是通配符意思。對每個字段運行match_phrase_prefix查詢,並合並每個字段的權重operator:"or" 默認"or"可不寫,表示query中的數據分詞后匹配中一個詞條則該文檔符合,"and"表示query中的數據分詞后需要全部匹配上的文檔才符合[比較復雜未實驗]
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "小明 小紅",
"fields": [
"username",
"nickname"
],
"type": "phrase"
}
}
]
}
}
}
- prefix
說明:搜索指定字段在倒排索引中的詞條以指定內容開頭的文檔,指定的字段不分詞
{
"query": {
"bool": {
"must": [
{
"prefix": {
"username": {
"value": "阿東"
}
}
}
]
}
}
}
- regexp/wildcard
說明:正則匹配。與
prefix
前綴查詢的特性類似,wildcard
通配符查詢也是一種底層基於詞的查詢, 與前綴查詢不同的是它允許指定匹配的正則式。它使用標准的 shell 通配符查詢:?
匹配任意字符,*
匹配 0 或多個字符
{
"query": {
"wildcard": {
"postcode": "W?F*HW"
}
}
}
wildcard
和 regexp
查詢的工作方式與 prefix
查詢完全一樣,它們也需要掃描倒排索引中的詞列表才能找到所有匹配的詞,然后依次獲取每個詞相關的文檔 ID ,與 prefix
查詢的唯一不同是:它們能支持更為復雜的匹配模式。
這也意味着需要同樣注意前綴查詢存在性能問題,對有很多唯一詞的字段執行這些查詢可能會消耗非常多的資源,所以要避免使用左通配這樣的模式匹配(如: *foo
或 .*foo
這樣的正則式)。
數據在索引時的預處理有助於提高前綴匹配的效率,而通配符和正則表達式查詢只能在查詢時完成,盡管這些查詢有其應用場景,但使用仍需謹慎。
- dis_max
說明:在多字段全文檢索時,固定相關度評分,不計算相關度評分,而是盡可能多的field匹配了少數的關鍵詞(取分數最高的那個字段的分數);
dis_max
查詢只會簡單地使用單個最佳匹配語句的評分_score
作為整體評分參數如下:
queries:[] 多匹配條件
boost:
tie_breaker:0.3 可以通過指定
tie_breaker
這個參數將其他匹配語句的評分也考慮其中,指定后算法如下:1. 獲取最佳匹配語句的評分``_source`` 2. 將其他匹配語句的評分結果與``tie_breaker``相乘 3. 對以上評分求和,並規范化
有了
tie_breaker
,會考慮所有匹配語句,但最佳匹配語句依然占最終結果里的很大一部分。https://www.elastic.co/guide/cn/elasticsearch/guide/current/_tuning_best_fields_queries.html
{
"query": {
"dis_max": {
"queries": [
{
"term": {
"status": 1
}
},
{
"match": {
"address": "zhejiang"
}
}
]
}
}
}
- boost
說明:讓一個查詢語句比其他語句更重要
查詢時的權重提升 是可以用來影響相關度的主要工具,任意類型的查詢都能接受
boost
參數。 將boost
設置為2
,並不代表最終的評分_score
是原值的兩倍;實際的權重值會經過歸一化和一些其他內部優化過程。盡管如此,它確實想要表明一個提升值為2
的句子的重要性是提升值為1
語句的兩倍。在實際應用中,無法通過簡單的公式得出某個特定查詢語句的 “正確” 權重提升值,只能通過不斷嘗試獲得。需要記住的是
boost
只是影響相關度評分的其中一個因子;它還需要與其他因子相互競爭。在前例中,title
字段相對content
字段可能已經有一個 “缺省的” 權重提升值,這因為在 字段長度歸一值 中,標題往往比相關內容要短,所以不要想當然的去盲目提升一些字段的權重。選擇權重,檢查結果,如此反復。https://www.elastic.co/guide/cn/elasticsearch/guide/current/query-time-boosting.html
GET /docs_2014_*/_search
{
"indices_boost": {
"docs_2014_10": 3,
"docs_2014_09": 2
},
"query": {
"match": {
"text": "quick brown fox"
}
}
}
- _source
說明:指定返回字段
{
"_source": ["oss_name","osp_name"],
}
驗證查詢的合法性
GET station/_validate/query?explain
{
"query": {
"match": {
"sku_name_string": "0# 柴油 國Ⅴ 0# 柴油 國Ⅵ"
}
}
}
正確返回:
{
"valid": true,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "station",
"valid": true,
"explanation": "sku_name_string:0# sku_name_string:柴油 sku_name_string:國Ⅴ sku_name_string:0# sku_name_string:柴油 sku_name_string:國Ⅵ"
}
]
}
錯誤返回:
{
"valid": false,
"error": "org.elasticsearch.common.ParsingException: no [query] registered for [sku_name_string]"
}
高亮我們的搜索
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
多索引關聯查詢
一下查詢意思為:從info索引中取出id為1的數據的user_id,做為user索引中等於user_id的條件條件,取出如何條件數據的user_id、status
terms中可以這么使用
match中不可以這么使用
"[match] query does not support [index]"
POST user/_search
{
"_source": [
"user_id",
"status"
],
"query": {
"terms": {
"user_id": {
"index": "info",
"type": "_doc",
"id": 1,
"path": "user_id"
}
}
}
}
通過ids查詢
POST myIndex/_search
{
"query": {
"ids": {
"values": [300,301]
}
}
}
檢測分詞
一下會根據myIndex中fieldName的分詞規則來分text的內容
POST myIndex/_analyze
{
"field": "fieldName",
"text": "你好 很高興"
}
返回內容格式如下
{
"tokens" : [
{
"token" : "你好",
"start_offset" : 0,
"end_offset" : 8,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "很高心",
"start_offset" : 9,
"end_offset" : 17,
"type" : "<ALPHANUM>",
"position" : 1
}
]
}
在查詢過程中,除了判斷文檔是否滿足查詢條件外,es還會計算一個_score來標示匹配的程度,旨在判斷目標文檔和查詢條件匹配的 有多好;
post: http://ip:端口號/索引(index)/_search【關鍵詞】(指定查詢)
{
"query【關鍵詞】(指定條件查詢)" : {
//方式1 match 先將搜索的內容拆詞,拆成不重復的詞條后,每個詞條與倒排索引中詞條匹配,operator默認為"or" 表示有一個相同,則該文檔符合搜索,如果operator為"and"表示需要數據包含所有搜索的分詞
"match【關鍵詞】(代表不是所有內容,有條件)" : {
"屬性名" : {
"query" : "屬性值",
"operator" : ""
}
}
//方式2 match_phrase 先將搜索的內容拆詞,拆成詞條后,每個詞條與倒排索引中詞條匹配,同時匹配上所有搜索內容的詞條,並且順序一樣,則該文檔符合搜索
//例如:
// 文檔:我的名字叫小明
// 搜索:明 則沒有結果
// 原因:我的名字叫小明 倒排索引中(我、的、名字叫、名字、叫、小明) 沒有"明"所以沒有匹配上
"match_phrase【關鍵詞】 (代表不是所有內容,有條件)" : {
"屬性名" : "屬性值"
}
//方式3 multi_match 先將搜索的內容拆詞,拆成詞條后,每個詞條與倒排索引中只是field屬性的詞條匹配,field屬性的詞條中至少一個與搜索內容的詞條相同,則該文檔符合搜索
"multi_match【關鍵詞】 (代表多個屬性符合一個條件查詢)" : {
"query【關鍵詞】(查詢內容)" : "內容值",
"fields【關鍵詞】(需要服務上面query的條件的屬性)" : ["屬性1","屬性2"],,
"type": "best_fields", //對匹配到兩個以上的分值*2 most_fields:匹配程度越高分值越高 cross_fields:詞條的分詞是匹配到不同字段中的,好像沒什么用
"tie_breaker": 2
}
//方式4 query_string 代表語法查詢
"query_string【關鍵詞】(代表語法查詢)" : {
"query【關鍵字】(查詢條件)" : "aaa", //表示所有文檔的任意一個屬性包含aaa的數據
//"query【關鍵字】(查詢條件)" : "aaa AND bbb ", //表示所有文檔的任意一個屬性包含aaa和bbb的數據
//"query【關鍵字】(查詢條件)" : "(aaa AND bbb) OR ccc ", //表示所有文檔的任意一個屬性包含aaa和bbb 或者 包含ccc 的數據
//"query【關鍵字】(查詢條件)" : "(aaa AND bbb) OR ccc ",
//"fields【關鍵詞】(指定匹配的屬性)" : //表示所有文檔的指定屬性包含aaa和bbb 或者 包含ccc 的數據
}
//方式5 term 字段查詢,對字段進行精確匹配,不拆分搜索內容,對text類型字段,如果該字段分詞了,搜索內容與倒排索引中有一個相同,則該文檔符合搜索條件,text類型字段分詞方案由創建索引時analyze確;
//如果搜索的內容是一個詞,match、match_phrase效果一樣,因為match、match_phrase對搜索內容進行非,但只能分成一個詞,一個詞然后匹配倒排索引中相同的文檔,效果和term一樣;
"term【關鍵詞】(指定字段查詢)" : {
"屬性名" : "屬性值" //查詢屬性名為屬性值的數據,如果文檔中有匹配的詞,但是沒有查詢出來,可能是這個字段使用的analyze, 搜索的屬性值不在分詞的詞條內;或者創建時聲明not_analyzed
}
"terms【關鍵詞】(指定包含查詢)": {
"屬性名" : ["屬性值1","屬性值2","屬性值3"]
}
//range 范圍查詢 值處可用關鍵詞"now" 表示當前日期
"range【關鍵詞】(范圍查詢)" : {
"屬性值(number)" : {
"對比方式開始(gte)" : "值(1000)",
"對比方式結束(lte)" : "值(2000)"
}
}
}
}
復雜類型嵌套
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "eggs"
}
},
{
"nested": {
"path": "一級屬性名",
"query": {
"bool": {
"must": [
{
"match": {
//可修改為不同篩選條件
"一級屬性名.二級屬性名": "屬性值"
}
},
{
"match": {
"一級屬性名.二級屬性名": "屬性值"
}
}
]
}
}
}
}
]
}}}
范圍搜索
distance:arc/plane/sloppy_arc
arc:最慢但最精確的是
arc
計算方式,這種方式把世界當作球體來處理。不過這種方式的精度有限,因為這個世界並不是完全的球體 plane:計算方式把地球當成是平坦的,這種方式快一些但是精度略遜。在赤道附近的位置精度最好,而靠近兩極則變差
sloppy_arc:如此命名,是因為它使用了 Lucene 的 SloppyMath 類。這是一種用精度換取速度的計算方式, 它使用 Haversine formula 來計算距離。它比 arc 計算方式快 4 到 5 倍,並且距離精度達 99.9%。這也是默認的計算方式。
geo_distance:查找距離某個中心點距離在一定范圍內的位置
500km以內
{
"must": [
{
"geo_distance": {
"distance": "500km",
"location": {
"lat": "24.46667",
"lon": "118.1"
}
}
}
]
}
geo_bounding_box:查找某個長方形區域內的位置
{
"must": [
{
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 40.8,
"lon": -74
},
"bottom_right": {
"lat": 40.715,
"lon": -73
}
}
}
}
]
}
geo_distance_range:查找距離某個中心的距離在min和max之間的位置
{
"must": {
"geo_distance_range": {
"gte": "1km",
"lt": "2km",
"location": {
"lat": 40.715,
"lon": -73.988
}
}
}
}
geo_polygon:查找位於多邊形內的地點。
數據排序
普通排序
{
"sort": [
{
"FIELD": {
"order": "desc"
}
}
]
}
距離排序
{
"sort": [
{
"_geo_distance": {
"order": "desc",
"unit": "km",
"distance_type": "plane",
"location": {
"lat": 40,
"lon": -70
}
}
}
]
}
復雜結構排序
以下排序規則:以復雜類型products中pro_status為-1的數據中最低一條的price_base降序;
{
"size": 300,
"_source": [
"products.price_base",
"products.pro_status"
],
"sort": [
{
"products.price_base": {
"order": "desc",
"mode": "min",
"nested": {
"path": "products",
"filter": {
"term": {
"products.pro_status": -1
}
}
}
}
}
]
}
排序條件
排序條件只能針對於以復雜類型數據排序,確定以復雜類型中的某一個子數據排序
nested中只可以使用過濾
filter
,不過可以在filter
中嵌套bool
;bool
是一個過濾集合,可以對復雜類型進行多個條件過濾;
{
"size": 300,
"_source": [
"products.price_base",
"products.pro_status"
, "products.sku"
],
"sort": [
{
"products.price_base": {
"order": "desc",
"mode": "max",
"nested": {
"path": "products",
"filter": {
"bool": {
"must": [
{
"term": {
"products.pro_status": 1
}
},
{
"match": {
"products.sku" : "D120G06"
}
}
]
}
}
}
}
}
]
}
Geohashes
https://www.elastic.co/guide/cn/elasticsearch/guide/current/geohashes.html
是一種將經緯度坐標(
lat/lon
)編碼成字符串的方式。 這么做的初衷只是為了讓地理位置在 url 上呈現的形式更加友好,但現在 geohashes 已經變成一種在數據庫中有效索引地理坐標點和地理形狀的方式。把整個世界分為 32 個單元的格子 —— 4 行 8 列 —— 每一個格子都用一個字母或者數字標識。比如
g
這個單元覆蓋了半個格林蘭,冰島的全部和大不列顛的大部分。每一個單元還可以進一步被分解成新的 32 個單元,這些單元又可以繼續被分解成 32 個更小的單元,不斷重復下去。gc
這個單元覆蓋了愛爾蘭和英格蘭,gcp
覆蓋了倫敦的大部分和部分南英格蘭,gcpuuz94k
是白金漢宮的入口,精確到約 5 米。換句話說, geohash 的長度越長,它的精度就越高。如果兩個 geohashes 有一個共同的前綴—
gcpuuz
—就表示他們挨得很近。共同的前綴越長,距離就越近。
- 概念
- 創建可Geohashes映射
以下設置, geohash 前綴中 1 到 7 的部分將被索引,所能提供的精度大約在 150 米
geohash_prefix:true 使用指定精度來索引 geohash 的前綴
geohash_precision:"1km" 代表的 geohash 的長度,也可以是一個距離。 1km 的精度對應的 geohash 的長度是 7
PUT /attractions
{
"mappings": {
"restaurant": {
"properties": {
"name": {
"type": "string"
},
"location": {
"type": "geo_point",
"geohash_prefix": true,
"geohash_precision": "1km"
}
}
}
}
}
- geohashes_cell
查詢做的事情非常簡單: 把經緯度坐標位置根據指定精度轉換成一個 geohash ,然后查找所有包含這個 geohash 的位置——這是非常高效的查詢。
precision
字段設置的精度不能高於映射時geohash_precision
字段指定的值。此查詢將
lat/lon
坐標點轉換成對應長度的 geohash —— 本例中為dr5rsk
—然后查找所有包含這個短語的位置。geohash 實際上僅是個矩形,而指定的點可能位於這個矩形中的任何位置。有可能這個點剛好落在了 geohash 單元的邊緣附近,但過濾器會排除那些落在相鄰單元的餐館。
{
"query": {
"constant_score": {
"filter": {
"geohash_cell": {
"location": {
"lat": 40.718,
"lon": -73.983
},
"precision": "2km"
}
}
}
}
}
聚合查詢
概念
聚合查詢就是用桶和指標不同的組合簽到出來的結果
聚合是基於倒排索引創建的,倒排索引是 后置分析( post-analysis )的。
桶(Buckts): 對特定條件的文檔的集合
指標(Metrics): 對桶內文旦進行統計計算
語法
- terms
說明:terms桶,為每個碰到的唯一詞項動態創建新的桶。
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
}
}
}
}
- avg
說明:計算桶內字段平均值
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
- 二連桶
說明:先放E,然后Q最遠距離Q桶,抬手時迅速轉移鼠標到第二個桶的位置,eqe
- 桶嵌套
說明:一下是統計每個顏色的汽車制造商的分布:
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
},
"make": {
"terms": {
"field": "make"
}
}
}
}
}
}
結果:
{
...
"aggregations": {
"colors": {
"buckets": [
{
"key": "red",
"doc_count": 4,
"make": {
"buckets": [
{
"key": "honda",
"doc_count": 3
},
{
"key": "bmw",
"doc_count": 1
}
]
},
"avg_price": {
"value": 32500
}
},
...
}
- min/max
說明:每個顏色中的每個make商的最低價和最高價
{
"size" : 0,
"aggs": {
"colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": { "avg": { "field": "price" }
},
"make" : {
"terms" : {
"field" : "make"
},
"aggs" : {
"min_price" : { "min": { "field": "price"} },
"max_price" : { "max": { "field": "price"} }
}
}
}
}
}
}
結果:
{
...
"aggregations": {
"colors": {
"buckets": [
{
"key": "red",
"doc_count": 4,
"make": {
"buckets": [
{
"key": "honda",
"doc_count": 3,
"min_price": {
"value": 10000
},
"max_price": {
"value": 20000
}
},
{
"key": "bmw",
"doc_count": 1,
"min_price": {
"value": 80000
},
"max_price": {
"value": 80000
}
}
]
},
"avg_price": {
"value": 32500
}
},
...
- histogram/sum
說明:根據指定字段按照指定間隔值分桶
參數有:
"field": "price", 指定的字段
"interval": 20000 分桶的間隔數值,20000一下可以得出每個interval區間的price的總和
{
"size" : 0,
"aggs":{
"price":{
"histogram":{
"field": "price",
"interval": 20000
},
"aggs":{
"revenue": {
"sum": {
"field" : "price"
}
}
}
}
}
}
- date_histogram
說明:按照時間分桶
屬性有:
field 字段
interval字段支持多種關鍵字:
year
,quarter
,month
,week
,day
,hour
,minute
,second
或者1.5h
,1M
format 返回的結果可以通過設置format進行格式化。
"time_zone":"+08:00" 日期支持時區的表示方法,這樣就相當於東八區的時間。
"offset":"+6h" 認情況是從凌晨0點到午夜24:00,如果想改變時間區間,可以通過下面的方式,設置偏移值。
"missing":"2000-01-01" 當遇到沒有值的字段,就會按照缺省字段missing value來計算
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "month",
"format": "yyyy-MM-dd"
}
}
}
}
- 返回空buckets
說明:
date_histogram
(和histogram
一樣)默認只會返回文檔數目非零的 buckets。min_doc_count 參數返回最小doc數的buckets,設置為0 表示為空的buckets也返回
extended_bounds: { min : "", "max": ""} 返回的結果返回,將不存在查詢范圍的buckets插入到返回結果中
{
"size" : 0,
"aggs": {
"sales": {
"date_histogram": {
"field": "sold",
"interval": "month",
"format": "yyyy-MM-dd",
"min_doc_count" : 0,
"extended_bounds" : {
"min" : "2014-01-01",
"max" : "2014-12-31"
}
}
}
}
}
- global
說明:全局桶,包含 所有 的文檔,它無視查詢的范圍。因為它還是一個桶,我們可以像平常一樣將聚合嵌套在內
"global":{} 全局桶沒有參數
{
"size" : 0,
"query" : {
"match" : {
"make" : "ford"
}
},
"aggs" : {
"single_avg_price": {
"avg" : { "field" : "price" }
},
"all": {
"global" : {},
"aggs" : {
"avg_price": {
"avg" : { "field" : "price" }
}
}
}
}
}
聚合和過濾
聚合范圍限定還有一個自然的擴展就是過濾。因為聚合是在查詢結果范圍內操作的,任何可以適用於查詢的過濾器也可以應用在聚合上。
- 過濾桶
說明:當文檔滿足過濾桶的條件時,我們將其加入到桶內。先將滿足filter過濾的文檔放在一個桶中,再基於這個桶執行avg
{
"size" : 0,
"query":{
"match": {
"make": "ford"
}
},
"aggs":{
"recent_sales": {
"filter": {
"range": {
"sold": {
"from": "now-1M"
}
}
},
"aggs": {
"average_price":{
"avg": {
"field": "price"
}
}
}
}
}
}
- post_filter
說明:對搜索結果聚合后再進行過濾
例如一下:查詢所有status為3的文檔,在對這些文檔進行order_type統計,統計后再對status為3的文檔進行oss_id=101的過濾。
{
"size": 0,
"query": {
"match": {
"status": {
"query": "3"
}
}
},
"post_filter": {
"term": {
"oss_id": "101"
}
},
"aggs": {
"all_order_type": {
"terms": {
"field": "order_type",
"size": 10
}
}
}
}
結果:
可以看出status=3的所有文檔的每個order_type中的文檔數量,和status=3 and oss_id=101的文檔數量total是199,上面我設置size=0不展示文檔信息,可調整size獲取status=3 and oss_id=101的文檔詳細信息
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 199,
"max_score": 0,
"hits": []
},
"aggregations": {
"all_order_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 11,
"doc_count": 51421
},
{
"key": 21,
"doc_count": 956
},
{
"key": 12,
"doc_count": 753
},
{
"key": 19,
"doc_count": 173
},
{
"key": 31,
"doc_count": 32
}
]
}
}
}
內置桶排序
說明:默認的,桶會根據
doc_count
降序排列,可設置order調整排序,如下_count:以文檔doc_count排序
_term:按詞項的字符串值的字母順序排序。只在
terms
內使用_key:按每個桶的鍵值數值排序(理論上與
_term
類似)。 只在histogram
和date_histogram
內使用
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color",
"order": {
"_count" : "asc"
}
}
}
}
}
根據度量計算結果(平均值、總和等),如下
先根據顏色分桶,在統計每個桶中price的平均值,然后根據每個桶平均值排序每個桶
{
"size" : 0,
"aggs" : {
"colors" : {
"terms" : {
"field" : "color",
"order": {
"avg_price" : "asc"
}
},
"aggs": {
"avg_price": {
"avg": {"field": "price"}
}
}
}
}
}
- extend_stats (TODO)
- cardinality
說明:去重 等價於sql: SELECT COUNT(DISTINCT color) FROM cars;
參數:
field:字段名
precision_threshold:這個閾值定義了在何種基數水平下我們希望得到一個近乎精確的結果。https://www.elastic.co/guide/cn/elasticsearch/guide/current/cardinality.html 不是很懂
如下,統計order_type共多少
{
"size": 0,
"aggs": {
"status_count": {
"cardinality": {
"field": "order_type"
}
}
}
}
結果:order_type共5個
{
"took": 29,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 199,
"max_score": 0,
"hits": []
},
"aggregations": {
"status_count": {
"value": 5
}
}
}
配合terms使用如下
統計個狀態訂單有幾種類型
{
"size": 0,
"aggs": {
"status_group": {
"terms": {
"field": "status"
},
"aggs": {
"order_type": {
"cardinality": {
"field": "order_type"
}
}
}
}
}
}
結果:去除部分不重要的信息
{
"aggregations": {
"status_group": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 3,
"doc_count": 53335,
"order_type": {
"value": 5
}
},
{
"key": 0,
"doc_count": 1755,
"order_type": {
"value": 4
}
}
]
}
}
}
- percentiles
說明:某以具體百分比下觀察到的數值。
https://www.elastic.co/guide/cn/elasticsearch/guide/current/percentiles.html
- fielddata
設想我們正在運行一個網站允許用戶收聽他們喜歡的歌曲。 為了讓他們可以更容易的管理自己的音樂庫,用戶可以為歌曲設置任何他們喜歡的標簽,這樣我們就會有很多歌曲被附上
rock(搖滾)
、hiphop(嘻哈)
和electronica(電音)
,但也會有些歌曲被附上my_16th_birthday_favorite_anthem
這樣的標簽。現在設想我們想要為用戶展示每首歌曲最受歡迎的三個標簽,很有可能
rock
這樣的標簽會排在三個中的最前面,而my_16th_birthday_favorite_anthem
則不太可能得到評級。 盡管如此,為了計算最受歡迎的標簽,我們必須強制將這些一次性使用的項加載到內存中。https://www.elastic.co/guide/cn/elasticsearch/guide/current/_fielddata_filtering.html
- 地理位置聚合
https://www.elastic.co/guide/cn/elasticsearch/guide/current/geo-aggs.html
POST:http://ip:端口號/索引(index)/_search【關鍵詞】(指定查詢)
{
//方式1
"aggs【關鍵詞】(指定聚合查詢)" : {
"聚合查詢名稱1 例如:group_by_age 根據年齡分組,返回結果在返回json 數組中,key為名稱" : {
"trems【關鍵詞】(本組聚合內容)" : {
"field【關鍵詞】(指定屬性)" : "屬性名"
}
},
"聚合查詢名稱2例如:group_by_sex 根據性別分組,返回結果和1 並列在數組中,key為名稱" : {
"trems【關鍵詞】(本組聚合內容)" : {
"field【關鍵詞】(指定屬性)" : "屬性名"
}
},
}
//方式2 : 統計計算
//返回 count 數據條數、min 最小一條多少、max 最大一條多少、 avg 平均多少、 sum 共多少
"aggs" : {
"grades_word_count" : {
"stats【關鍵詞】(代表計算或者count/min/max/avg/sum指定計算的結果值)" : {
"field【關鍵詞】(指定屬性)" : "屬性名"
}
}
}
}
批量操作
除刪除外每條操作前面必須跟{"index":{"_index":"索引名","_type":"類型","_id":"x"}}
每一段json不能換行,第二段之間不能有空行 每行換行'\n'
前6行為添加 三條數據,7-8為更新,9為刪除
POST:_buld
{"index":{"_index":"zhouls","_type":"emp","_id":"10"}}
{ "name":"jack", "age" :18}
{"index":{"_index":"zhouls","_type":"emp","_id":"11"}}
{ "name":"jack", "age" :18}
{"index":{"_index":"zhouls","_type":"emp","_id":"12"}}
{"name":"tom", "age":27}
{"update":{"_index":"zhouls","_type":"emp", "_id":"2"}}
{"doc":{"age" :22}}
{"delete":{"_index":"zhouls","_type":"emp","_id":"1"}}
字段類型
elasticsearch6.0
基礎類型:
- 字符類型:
text、keyword
- 數字類型:
long、integer、short、byte、double、float、half_float、sacled_float
- 日期類型:
date
( "yyyy-mm-dd HH:mm:ss || yyyy-MM-dd||epoch_millis") - 布爾類型:
boolean
- 字節型:
binary
- 范圍型:
integer_range、float_range、long_range、double_rang、date_range
復雜類型:
- 數組類型(array):數組類型不需要明確聲明內容類型
- 類類型(object):只針對於一個json類型的類。
- 嵌套類型(nested):嵌套json數組
地標類型:
- 地標坐標(geo-point):經緯度坐標
- 地標形狀類型(geo_shape):復雜的圖形
特殊類型:
- ip類型(ip):IPv4、IPv6
- 自動完成類型(completion):會自動完成補全的類型.
- 令牌統計類型(token_count):統計字符串中的數量
- 哈希計算類型(murmur3):在創建索引的時候就會計算出哈希值並存儲
- 滲透類型(percolator):接受從query-dsl來的請求
- 聯合類型(join):定義同一個index中,document的子父的關系
Multi-Fields
有時候我們搜索的時候需要把一個字段的類型定義為full-text,當排序的時候又需要把它當做keyword類型,這個時候我們就需要使用Multi-Fields類型了,使用參考,可以使用fields來對大部分類型做Multi-Fields處理。
格式如下:
{
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
分詞器
-
standard 分詞器:英文的處理能力同於StopAnalyzer.支持中文采用的方法為單字切分。他會將詞匯單元轉換成小寫形式,並去除停用詞和標點符號
-
simple 分詞器:功能強於WhitespaceAnalyzer, 首先會通過非字母字符來分割文本信息,然后將詞匯單元統一為小寫形式。該分析器會去掉數字類型的字符
-
Whitespace 分詞器:僅僅是去除空格,對字符沒有lowcase化,不支持中文; 並且不對生成的詞匯單元進行其他的規范化處理。
-
Stop 分詞器:StopAnalyzer的功能超越了SimpleAnalyzer,在SimpleAnalyzer的基礎上增加了去除英文中的常用單詞(如the,a等),也可以更加自己的需要設置常用單詞;不支持中文
-
keyword 分詞器:KeywordAnalyzer把整個輸入作為一個單獨詞匯單元,方便特殊類型的文本進行索引和檢索。針對郵政編碼,地址等文本信息使用關鍵詞分詞器進行索引項建立非常方便。
-
pattern 分詞器:一個pattern類型的analyzer可以通過正則表達式將文本分成"terms"(經過token Filter 后得到的東西 )。接受如下設置:
一個 pattern analyzer 可以做如下的屬性設置:
lowercaseterms是否是小寫. 默認為 true 小寫.pattern正則表達式的pattern, 默認是 \W+.flags正則表達式的flagsstopwords一個用於初始化stop filter的需要stop 單詞的列表.默認單詞是空的列表
-
language 分詞器:一個用於解析特殊語言文本的analyzer集合。不支持中文。
-
snowball 分詞器:一個snowball類型的analyzer是由standard tokenizer和standard filter、lowercase filter、stop filter、snowball filter這四個filter構成的。
snowball analyzer 在Lucene中通常是不推薦使用的。
-
Custom 分詞器:是自定義的analyzer。允許多個零到多個tokenizer,零到多個 Char Filters. custom analyzer 的名字不能以 "_"開頭.
The following are settings that can be set for a custom analyzer type:
SettingDescriptiontokenizer通用的或者注冊的tokenizer.filter通用的或者注冊的token filterschar_filter通用的或者注冊的 character filtersposition_increment_gap距離查詢時,最大允許查詢的距離,默認是100
-
ik-analyzer:中文分詞器,需要手動安裝。
中文分詞器安裝
選擇適合的版本 下載
https://github.com/medcl/elasticsearch-analysis-ik/releases
在你的es安裝目錄中的plugin中新建ik目錄
解壓下載的elasticsearch-analysis-ik-6.2.4內容copy到ik中
自定義詞典
cd ik/config
vim yourdic.dic 一行代表一個詞
vim IKAnalyzer.cfg.xml
<!--用戶可以在這里配置自己的擴展字典 -->
<entry key="ext_dict">yourdic.dic</entry>
<!--用戶可以在這里配置自己的擴展停止詞字典-->
重啟elasticsearch
測試中文分詞器
創建索引、使用中文分詞
PUT user
{
"mappings": {
"xiaoming" : {
"properties": {
"name" : {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
插入數據
POST user/xiaoming
{
"name" : "我的名字叫小明"
}
查看分詞效果
GET user/_analyze
{
"field": "name",
"text": "我的名字叫小明"
}
結合PHP
-
安裝elasticSearch PHP擴展(注意版本)
"elasticsearch/elasticsearch": "~6.0"
ERROR
-
No handler for type [string] declared on field [first_name]"}
- 表示elasticsearch6.0里面不支持string類型,只有text、keyword類型
-
Result window is too large, from + size must be less than or equal to: [10000]
- ES提示我結果窗口太大了,目前最大值為10000,而我卻要求給我10000000。並且在后面也提到了要求我修改
index.max_result_window
參數來增大結果窗口大小。
curl -XPUT http://127.0.0.1:9200/indexName/_settings -d '{ "index" : { "max_result_window" : 100000000}}'
- ES提示我結果窗口太大了,目前最大值為10000,而我卻要求給我10000000。並且在后面也提到了要求我修改
-
FORBIDDEN/12/index read-only / allow delete (api)];
磁盤滿了后 es會將數據設置只讀鎖起來
解決方案:
1 解鎖,刪除一部分數據,將服務器中磁盤空間清理
2 加磁盤
//設置所有非只讀模式
PUT _settings
{
"index": {
"blocks": {
"read_only_allow_delete": "false"
}
}
}
//獲取索引信息
GET queue/_settings?pretty
//設置指定索引為非只讀模式
PUT queue/_settings
{
"index.blocks.read_only_allow_delete": false
}
// 清空指定索引
POST queue/list/_delete_by_query?conflicts=proceed
{
"query" : {
"match_all" :{}
}
}
//查詢es中磁盤使用情況
GET _cat/allocation?v
-
missing authentication token for REST request
沒有權限
-
Whitespace 空格分詞 實測可用
-
search_analyzer 對請求的數據分詞方式 analyzer 對es中數據分詞
-
自定義分詞需要先向es中設置分詞方式 例如逗號分詞,再和普通設置分詞方式相同設置分詞方式為設置的名字,一下案例中分詞名為都douhao
curl -XPOST 'http://172.18.0.4:9200/demo/?pretty' -d '
{
"settings":
{
"analysis":
{
"analyzer":
{
"douhao":
{
"type":"pattern",
"pattern":","
}
}
}
}
}'
-
分詞只對text類型數據有效,keyword為整個值為一個詞,其實就相當於沒有分詞
-
復雜類型中array 表示一個屬性的值為一個數組,如下,數組中的數據類型必須相同
"a" : ["1","2","3"]
- Elastic search 6以前復雜類型會有
object
如下1,elastic search6以后沒有object
默認類型嵌套處理如下2
{
"gb": {
"tweet":
"properties": {
"tweet": { "type": "string" },
"user": {
"type": "object",
"properties": {
"id": { "type": "string" },
"gender": { "type": "string" },
"age": { "type": "long" },
"name": {
"type": "object",
"properties": {
"full": { "type": "string" },
"first": { "type": "string" },
"last": { "type": "string" }
}
}
}
}
}
}
}
}
{
"test": {
"mappings": {
"test": {
"properties": {
"tweet": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"user": {
"properties": {
"age": {
"type": "long"
},
"gender": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"properties": {
"first": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"full": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"last": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
}
}
}
}
-
嵌套對象 nested 與
object`最大的區別是 nested會將嵌套中的每條數據當成一個整體,
object``會將嵌套數據中相同屬性數據索引在一起,這樣搜索就產生混亂 舉例如下一條數據有一個嵌套字段 其中包含兩條數據
[{ "name" : "a", "age":2},{"name":"b","age","2"}]
搜索條件是 name = a, age = 2
如果是object類型就會搜出來 它會這樣索引 name:["a","b"], age:["1","2"] 這樣 a在name中匹配上,2在age中匹配上,所以就能搜到,
nested 則不會,它會將
{ "name" : "a", "age":2}
,{"name":"b","age","2"}]
分別獨立