PUT /test_index
PUT /test_index/doc/1
{
"username":"alfred",
"age":1
}
创建文档时,如果索引不存在,es会自动创建对应的index和type - 不指定id创建文档api如下:
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中发送到es
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" #指定分词器
}
}
}
}
}
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"
}
}
}
]
}
}
}
首先创建一个文档
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中
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类型直接替换成keyword
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如下所示:
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"
}
}
}
GET test_index_index/_search
{
"query":{
"query_string":{
"default_field":"remote_ip",
"query":"171.22.12.14"
}
}
}
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
}
}
}
- has_child返回包含某子文档的父文档
GET blog_index_parent/_search
{
"query":{
"has_child":{#关键词
"type":"comment",#指明子文档类型
"query":{
"match":{
"comment":"world"
}
}
}
}
}
- has_parent返回某父文档的子文档
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"
}
}