PUT /test_index
PUT /test_index/doc/1 { "username":"alfred", "age":1 }
建立文档时,若是索引不存在,es会自动建立对应的index和typehtml
POST /test_index/doc { "username":"tom", "age":20 }
GET /test_index/doc/1
GET /test_index/doc/_search { "query":{ "term":{ "_id":"1" } } }
查询语句,json格式,放在http body中发送到esjava
POST _bulk {"index":{"_index":"test_index","_type":"doc","_id":"3"}} {"username":"alfred","age":10} {"delete":{"_index":"test_index","_type":"doc","_id":"1"}}
GET /_mget { "doc":[ { "_index":"test_index", "_type":"doc", "_id":"1" }, { "_index":"test_index", "_type":"doc", "_id":"2" } ] }
文档id | 文档内容 |
---|---|
1 | elasticsearch是最流行的搜索引擎 |
2 | PHP是世界上最好的语言 |
3 | 搜索引擎是如何诞生的 |
单词 | 文档ID列表 |
---|---|
elasticsearch | 1 |
流行 | 1 |
搜索引擎 | 1,3 |
世界 | 2 |
POST _analyze { "analyzer":"standard", #分词器 "text":"hello,world" #测试文本 }
POST _analyze { "tokenizer":"standard", "filterf":["lowercase"], #自定义analyzer "text":"hello world" }
POST _analyze { "tokenizer":"keyword", #keyword类型的Tokenizer能够直接看到输出结果 "char_filter":["html_strip"], #指明要使用的char_filter "text":"<p>I'm so <b>happy</b>!</p>" }
POST _analyze { "tokenizer":"path_hierarchy", "text":"/one/two/three" }
POST _analyze { "text":"a hello world", "tokenizer":"standard", "filter":[ "stop", "lowercase", { "type":"ngram", "min_gram":4, "max_gram":4 } ] }
PUT test_index { "settings":{ "analysis":{ "char_filter":{}, "tokenizer":{}, "filter":{}, "analyzer":{} } } }
PUT test_index { "mappings":{ "doc":{ "properties":{ "title":{ "type":"text", "analyzer":"whitespace" #指定分词器 } } } } }
查询时分词的指定方式有以下几种:node
POST test_index/_search { "query":{ "match":{ "message":{ "query":"hello", "analyzer":"standard" } } } }
PUT test_index { "mappings":{ "doc":{ "properties":{ "title":{ "type":"text", "analyzer":"whitespace", "search_analyzer":"standard" } } } } }
PUT my_index { "mappings":{ "doc":{ "properties":{ "title":{ "type":"text" }, "name":{ "type":"keyword" }, "age":{ "type":"integer" } } } } }
PUT my_index { "mappings":{ "doc":{ "properties":{ "first_name":{ "type":""text", "copy_to":"full_name" }, "last_name":{ "type":"text", "copy_to":"full_name" }, "full_name":{ "type":"text" } } } } }
PUT my_index { "mappings":{ "doc":{ "properties":{ "cookie":{ "type":"text", "index":"false" } } } } }
PUT my_index { "mappings":{ "doc":{ "properties":{ "cookies":{ "type":"text", "index_options":"offsets" } } } } }
PUT my_index { "mappings":{ "my_type":{ "properties":{ "status_code":{ "type":"keyword", "null_value":"NULL" } } } } }
{ "test_index":{ "mappings":{ "doc":{ "properties":{ "username":{ "type":"text", "fields":{ "pinyin":{ "type":"text", "analyzer":"pinyin" } } } } } } } }
JSON类型 | es类型 |
---|---|
null | 忽略 |
Boolean | Boolean |
浮点类型 | float |
整数 | long |
object | object |
array | 有第一个非null值的类型决定 |
string | 匹配为日期则设为date类型(默认开启),匹配为数字的话设为float或long类型(默认关闭),设为text类型,并附带keyword的子字段 |
PUT mu_index { "mappings":{ "my_type":{ "dynamic_date_formats":["MM/dd/yyyy"], "date_detection":false } } }
PUT my_index { "mappings":{ "my_type":{ "numeric_detection":true } } }
PUT test_index { "mappings":{ "doc":{ "dynamic_templates":[#数组,可指定多个匹配规则 { "strings":{ #模板名称 "match_mapping_type":"string",#匹配规则 "mapping":{ "type":"keyword" } } } ] } } }
首先建立一个文档python
PUT my_index/doc/1 { "referrer": "-", "response":"200", "remote_ip":"171.22.12.14", "method":"POST", "user_name":"-", "http_version":"1.1", "body_sent":{ "bytes":"0" }, "url":"/analyzeVideo" }
es会根据建立的文档动态生成映射,能够直接将动态生成的映射直接复制到须要自定义的mapping中nginx
PUT test_index { "mappings": { "doc": { "properties": { "body_sent": { "properties": { "bytes": { "type": "long" } } }, "http_version": { "type": "keyword" }, "method": { "type": "keyword" }, "referrer": { "type": "keyword" }, "remote_ip": { "type": "keyword" }, "response": { "type": "long" }, "url": { "type": "text" }, "user_name": { "type": "keyword" } } } } }
这样定义的映射仍是比较多余,能够利用动态模板将string类型直接替换成keywordgit
DELETE test_index PUT test_index { "mappings": { "doc": { "dynamic_templates":[ { "strings":{ "match_mapping_type":"string", "mapping":{ "type":"keyword" } } } ], "properties": { "body_sent": { "properties": { "bytes": { "type": "long" } } }, "response": { "type": "long" }, "url": { "type": "text" } } } } }
索引模板API以下所示:github
PUT _template/test_template { "index_patterns":["te*","bar*"], "order":0, "settings":{ "number_of_shards":1, "number_of_replicas":0 }, "mappings":{ "doc":{ "_source":{ "enabled":false }, "properties":{ "name":{ "type":"keyword" } } } } }
GET test_index/_search { "query":{ "match":{ #关键词 "remote_ip":"171.22.12.14" #字段名 } } }
响应结果以下:正则表达式
{ "took": 4, #查询总用时 "timed_out": false, #是否超时 "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, #匹配文档总数 "max_score": 0.2876821, "hits": [ #返回文档列表 { "_index": "test_index_index", "_type": "doc", "_id": "1", "_score": 0.2876821, #文档相关度得分 "_source": { #文档原始内容 "referrer": "-", "response": "200", "remote_ip": "171.22.12.14", "method": "POST", "user_name": "-", "http_version": "1.1", "body_sent": { "bytes": "0" }, "url": "/analyzeVideo" } } ] } }
首先对查询语句进行分词,分词后分别根据字段的倒排索引进行匹配算分,并会匹配到一个或多个文档,再将匹配到的文档进行汇总得分,根据得分排序返回多个文档算法
GET test_index_index/_search { "query":{ "match_phrase":{ "remote_ip":"171.22.12.14" } } }
相似于URI Search中的q参数查询sql
GET test_index_index/_search { "query":{ "query_string":{ "default_field":"remote_ip", "query":"171.22.12.14" } } }
其经常使用的逻辑符号以下,不能使用AND、OR、NOT等关键词:
GET test_index_index/_search {
"query":{
"simple_query_string":{
"fields":["remote_ip"],
"query":"alfred +way"
}
}
}
将查询语句做为整个单词进行查询,即不对查询语句作分词处理,以下所示:
GET test_index_index/_search { "query":{ "term":{ "remote_ip":"171.22.12.14" } } }
范围查询主要针对数值和日期类型,以下所示:
GET test_index_index/_search { "query":{ "range":{ "response":{#找出响应状态码大于10,小于300的文档 "gt": 10, "lte":300 } } } }
针对日期的查询以下所示:
GET test_index_index/_search { "query":{ "range":{ "birth":{ "gt": "1990-01-01", "lte":"now-2h", "gt":"2019-01-01||+1M/d" } } } }
相关性算分的几个重要概念以下:
GET test_index_index/_search { "explain": true, "query":{ "match":{ "remote_ip":"171.22.12.14" } } }
GET test_index_index/_search { "query":{ "constant_score":{ "filter":{ "match": { "response":200 } } } } }
响应以下:
{ "took": 7, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1, "hits": [ { "_index": "test_index_index", "_type": "doc", "_id": "1", "_score": 1, "_source": { "referrer": "-", "response": "200", "remote_ip": "171.22.12.14", "method": "POST", "user_name": "-", "http_version": "1.1", "body_sent": { "bytes": "0" }, "url": "/analyzeVideo" } } ] } }
子句 | 内容 |
---|---|
filter | 只过滤符合条件的文档,不计算相关性得分 |
must | 文档必须符合must中的全部条件,会影响相关性得分 |
must_not | 文档必须不符合must_not中的全部条件 |
should | 文档能够符合should中的条件,会影响相关性得分 |
GET test_index_index/_search { "query":{ "bool":{ "filter":[ {} ], "should":[ {} ], "must":[ {} ], "must_not": [ {} ] } } }
查询response为200,ip为"171.22.12.14"的值
GET test_index_index/_search { "query":{ "bool":{ "must":[ { "match":{ "response":200 } }, { "match":{ "remote_ip": "171.22.12.14" } } ] } } }
上下文类型 | 执行类型 | 使用方式 |
---|---|---|
Query | 查询与查询语句最匹配的文档,对全部文档进行相关性算分并排序 | 1.query 2. bool中的must和should |
Filter | 查找与查询语句相匹配的文档,只过滤不算分,常用过滤器,ES会自动的缓存过滤器的内容,这对于查询来讲,会提升不少性能 | 1.bool中的filter与must_not 2.constant_score中的filter |
GET /_search { "query": { "bool": { "must": [ { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }} ], "filter": [ { "term": { "status": "published" }}, { "range": { "publish_date": { "gte": "2015-01-01" }}} ] } } }
GET test_index_index/_count { "query":{ "match":{ "response":200 } } }
响应以下:
{ "count": 1, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 } }
GET test_index/_search { "_source":false }
返回部分字段
GET test_index/_search { "_source":["response","name"] } GET test_index/_search { "_source":{ "includes":"*i*", "excludes":"remote_ip" } }
GET test_index/_search?search_type=dfs_query_then_fetch
GET test_search_index/_search { "sort":[ #关键字 { "birth":"desc" }, { "_score":"desc" }, { "_doc":"desc" } ] }
GET test_search_index/_search { "sort":{ "username":"desc" } } #会产生报错
GET test_search_index/_search { "sort":{ "username.keyword":"desc" } }
文档ID | 字段值 |
---|---|
1 | 100 |
2 | 89 |
3 | 129 |
对比 | fielddata | DocValues |
---|---|---|
建立时机 | 搜索时即时建立 | 索引时建立,与倒排索引建立时机一致 |
建立位置 | JVM Heap | 磁盘 |
优势 | 不会占用额外的磁盘空间 | 不会占用Heap内存 |
缺点 | 文档过多时,即时建立会花过多时间,占用过多Heap内存 | 减慢索引的速度,占用额外的磁盘资源 |
PUT test_search_index/_mapping/doc { "properties":{ "username":{ "type":"text", "fileddata":"true" } } }
PUT test_doc_value/ { "mappings":{ "doc":{ "properties": } } }
GET test_search_index/_search { "docvalue_fields":[ "username", "username.keyword", "age" ] }
total_page=(total+page_size-1)/page_size total为文档总数
GET test_search_index/_search?scrol=5m #该scroll快照有效时间 { "size":1 #指明每次scroll返回的文档数 }
post _search/scroll { "scroll":"5m", #指明有效时间 "scroll_id":"..." #上一步返回的id }
DELETE /_search/scroll { "scroll_id":[ "DXFZAD....", "DESGRHRH..." ] } DELETE /_search/scroll/_all
GET test_search_index/_search { "size":1, "sort":{ "age":"desc", "_id":"desc" } } GET test_search_index/_search { "size":1, "search_after":[28,"2"], "sort":{ "age":"desc", "_id":"desc" } }
类型 | 场景 |
---|---|
from/size | 须要实时获取顶部的部分文档,且须要自由翻页 |
scroll | 须要所有文档,如导出全部数据的功能 |
search_after | 须要所有文档,不须要自由翻页 |
GET test_search_index/_search { "size":0, "aggs":{ #关键词,与query同级 "<aggregation_name>":{#定义聚合名称 "<aggregation_type>":{#定义聚合类型 <aggregation_body> }, [,"aggs":{[<sub_aggregation>]+}]? #子查询 } [,"<aggregation_name_2>":{...}]* #能够包含多个聚合分析 } }
GET test_search_index/_search { "size":0, #不须要返回文档列表 "aggs":{ "min_age":{ "min":{ #关键词 "field":"age" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "max_age":{ "max":{ "field":"age" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "count_of_job":{ "cardinality":{ #关键词 "field":"job.keyword" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "stats_age":{ "stats":{ "field":"age" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "stats_age":{ "extended_status":{ "field":"age" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "per_age":{ "percentiles":{ #关键词 "field":"salary" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":10 }, "aggs":{ "top_employee":{ "top_hits":{ "size":10, "sort":[ { "age":{ "order":"desc" } } ] } } } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ #关键词 "field":"job.keyword",#指明term字段 "size":5 #指定返回数目 } } } }
GET test_search_index/_search { "size":0, "aggs":{ "salary_range":{ "range":{ #关键词 "field":"salary",\ "ranges":[ #指定每一个range的范围 { "to":1000 }, { "from":1000, "to":2000 } ] } } } }
GET test_search_index/_search { "size":0, "aggs":{ "date_range":{ "range":{ #关键词 "field":"birth", "format":"yyyy",#指定返回结果的日期格式 "ranges":[ { "from":"1980",#指定日期,可使用date math "to":"1990" }, { "from":"1990", "to":"2000" } ] } } } }
GET test_search_index/_search { "size":0, "aggs":{ "salary_hist":{ "histogram":{ #关键词 "field":"salary", "interval":5000, #指定间隔大小 "extended_bounds":{ #指定数据范围 "min":0, "max":40000 } } } } }
Get test_search_index/_search { "size":0, "aggs":{ "by_year":{ "date_historgram":{ #关键词 "field":"birth", "interval":"year", #指定间隔大小 "format":"yyyy" #指定日期格式化 } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":10 }, "aggs" } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ #第一层聚合 "terms":{ "field":"job.keyword", "size":10 }, "aggs":{ "salary":{ #第二层聚合 "stats":{ "field":"salary" } } } } } }
POST order/_search { "size":0, "aggs":{ "sales_per_month":{ "date_histogram":{ "field":"date", "interval":"month" }, "aggs":{ "sales":{ "sum":{ "field":"price" } } } }, "avg_monthly_sales":{ "avg_bucket":{ "bucket_path":"sales_per_month>sales" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":10 }, "aggs":{ "avg_salary":{ "avg":{ "field":"salary" } } } }, "min_salary_by_job":{ "min_bucket":{ #关键词 "buckets_path":"jobs>avg_salary" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":10 }, "aggs":{ "avg_salary":{ "avg":{ "field":"salary" } } } }, "max_salary_by_job":{ "max_bucket":{ "buckets_path":"jobs>avg_salary" } } } }
GET test_search_index/_search { "size":0, "aggs":{ "birth":{ "date_histogram":{ "field":"birth", "interval":"year", "min_doc_count":0 }, "aggs":{ "avg_salary":{ "avg":{ "field":"salary" } }, "derivative_avg_salary":{ "derivative":{ #关键词 "bucket_path":"avg_salary" } } } } } }
GET test_search_index/_search { "size":, "aggs":{ "birth":{ "date_histogram":{ "field":"birth", "interval":"year", "min_doc_count":0 }, "aggs":{ "avg_salary":{ "avg":{ "field":"salary" } }, "mavg_salary":{ "moving_avg":{ #关键词 "buckets_path":"avg_salary" } } } } } }
GET test_search_index/_search { "size":0, "query":{ "match":{#aggs做用域该query的结果集 "username":"alfred" } }, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":10 } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs_salary_small":{ "filter":{ "range":{ "salary":{ "to":10000 } } }, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword" } } } }, "jobs":{ "terms":{ "field":"job.keyword" } } } }
GET test_search_index/_search { "aggs":{ "jobs":{ "terms":{ "field":"job.keyword" } } }, "post_filter":{#过滤条件 "match":{ "job.keyword":"java engineer" } } }
GET test_search_index/_search { "query":{ "match":{ "job.keyword":"java engineer" } }, "aggs":{ "java_avg_salary":{ "avg":{ "field":"salary" } }, "all":{ "global":{}, "aggs":{ "avg_salary":{#过滤条件 "avg":{ "field":"salary" } } } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":10, "order":[ { "count":"asc" }, { "_key":"desc" } ] } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":1, "shard_size":10 } } } }
GET test_search_index/_search { "size":0, "aggs":{ "jobs":{ "terms":{ "field":"job.keyword", "size":2, "show_term_doc_count_error":true } } } }
PUT blog_index_parrent_child { "mappings":{ "doc":{ "properties":{ "join":{ "type":"join",#指明类型 "relations":{#指明父子关系 "blog":"comment" } } } } } }
#建立父文档 PUT blog_index_parent_child/doc/1 { "title":"blog", "join":"blog" } #建立子文档 PUT blog_index_parent_child/doc/comment-1?routing=1 #指定routing值,确保父子文档在一个分片上,通常使用父文档id { "comment":"comment world", "join":{ "name":"comment", #指明子类型 "parent":1 #指明父文档id } }
GET blog_index_parent/_search { "query":{ "parent_id":{#关键词 "type":"comment",#指明子文档类型 "id":"2" #指明父文档id } } }
GET blog_index_parent/_search { "query":{ "has_child":{#关键词 "type":"comment",#指明子文档类型 "query":{ "match":{ "comment":"world" } } } } }
GET blog_index_parent/_search { "query":{ "has_parent":{ "has_parent":"blog",#指定父文档类型 "query":{#指明父文档查询条件 "match":{ "title":"blog" } } } } }
对比 | Nested Object | Parent/Child |
---|---|---|
优势 | 文档存储在一块儿,所以读取性能高 | 父子文档能够独立更新,互不影响 |
缺点 | 更新父或子文档时须要更新整个文档 | 为了维护join的关系,须要占用部份内存,读取性能较差 |
场景 | 子文档偶尔更新,查询频繁 | 子文档更新频繁 |
POST blog_index/_update_by_query?conflicts=proceed #若是遇到版本冲突,覆盖并继续执行 POST blog_index/_update_by_query { "script":{ #更新文档的字段值 "source":"ctx._source.likes++", "lang":"painless" }, "query":{ #能够更新部分文档 "term":{ "user":"tom" } } }
POST _reindex { "source":{ "index":"blog_index" }, "dest":{ "index":"blog_new_index" } }
POST _reindex { "conflicts":"proceed",#冲突时覆盖并继续 "source":{ "index":"blog_index", "query":{ "term":{ "user":"tom" } } }, "dest":{ "index":"blog_new_index" } }
POST blog_index/_update_by_query?wait_for_completion=false #获取task ID GET _tasks/_qkdskglrfodsm(task ID)
PUT /_cluster/settings { "persistent":{ "discovery.zen.minimum_master_nodes":2 }, "transient":{ "indices.store.throttle.max_bytes_per_sec":"50mb" } }
欢迎各位关注个人公众号“没有故事的陈师傅”