创建索引前,先弄清楚这几个概念,index_template、index、setting、mapping;alais、ilm/policy;dynamic_template、dynamic_mapping。
es创建索引是相当灵活的,可以插入数据的时候,自动推断字段类型,生成索引【此时称为dynamic_mapping】;也可以先创建索引【index】,再插入数据,不过这个索引是一对一;也可以创建一个索引模板【index_template】,后面生成索引直接使用索引模板创建,就不需要为每个索引设置字段类型了,但是索引模板字段类型固定,也会出现一定局限,这时还可以使用动态模板【dynamic_template】做一些按条件生成索引。索引设置后,我们还可以为索引创建别名【alais】,这样当索引分片后(比如index1,index2),我们还可以通过一个统一名称去访问它,索引的数据存在冷、热、温不同的生命周期,我们可以通过设置索引的ilm/policy去实现。
1.2、字段类型Elasticsearch字段类型类似于MySQL中的字段类型。Elasticsearch字段类型主要有:核心类型、复合类型、多字段特性、特殊类型。
1.2.1、核心类型核心类型可以划分为字符串类型、数字类型、日期类型、布尔类型、基于BASE64的二进制类型、范围类型
类型
具体类型
二进制类型
binary
字符串类型
text、keyword
布尔类型
boolean
数字类型
long、integer、short、byte、double、float、half_float、scaled_float
日期类型
date、date_nanos
范围类型
range
字符串类型Elasticsearch7.x有两种字符串类型:text和keyword,在Elasticsearch5.x之后string类型已经不再支持。
text:text类型适用于需要被全文检索的字段,例如新闻正文、邮件内容等比较长的文字。text类型会被Lucene分词器(Analyzer)处理为一个个词项,并使用Lucene倒排索引存储。text字段不能被用于排序,无法模糊查询。keyword:keyword适合简短、结构化字符串,例如主机名、姓名、商品名称等,可以用于过滤、排序、聚合检索,也可以用于精确查询。保存一个字符串新字段,可以自动识别为text+keyword类型,当我们不想分词查询时,可以name.keyword进行查询。如果想将已有的text不分词,可以执行上面命令,再name.keyword进行查询。
数字类型
数字类型分为long、integer、short、byte、double、float、half_float、scaled_float,其范围如下:
long,?263到263-1integer,-231到231-1short,?32768到32767byte,?128到127double,IEEE754标准双精度浮点类型,8字节float,IEEE754标准单精度浮点类型,4字节half_float,IEEE754标准半精度浮点类型,2字节scaled_float,缩放类型浮点类型数字类型的字段在满足需求的前提下应当尽量选择范围较小的数据类型,字段长度越短,搜索效率越高。
日期类型在Elasticsearch中日期可以为以下形式:
格式化的日期字符串,例如2019-01-0100:00、2019/01/01时间戳(和1970-01-0100:00:00UTC的差值),单位毫秒或者秒即使是格式化的日期字符串,Elasticsearch底层依然采用的是时间戳的形式存储。
布尔类型
JSON文档中同样存在布尔类型,不过JSON字符串类型也可以被Elasticsearch转换为布尔类型存储,前提是字符串的取值为"true"或者"false"。布尔类型常用于检索中的过滤条件。
二进制类型
二进制类型binary接受BASE64编码的字符串,默认store属性为false,并且不可以被搜索。
范围类型
范围类型可以用来表达一个数据的区间,可以分为5种:
integer_range,可以表示最大的范围为[?231,231?1]float_range,可以表达IEEE754单精度浮点数范围long_range,可以表示最大的范围为[?263,263?1]double_range,可以表达IEEE754双精度浮点数范围date_range,可以表达64位时间戳(单位毫秒)范围1.2.2、复合类型复合类型主要有array【数组】、object【对象】、nested【嵌套】。
数组类型Lucene底层并不真正支持数组类型,所以Elasticsearch也没有专用的数组类型,依据数组元素类型定,每个元素必须是同一种类型。例如:tag:[1,2,3]、["a","b","c"]、[{"name":"Trump"},{"name":"Smith"}]是合法的。
{n"mappings":{n"properties":{n"tag":{n"type":"keyword"n}n}n}n}Object类型
JSON字符串允许嵌套对象,一个文档可以嵌套多个、多层对象。可以通过object类型来存储二级文档,不过由于Lucene并没有内部对象的概念,Elasticsearch会将原JSON文档扁平化,例如文档:
{"name":{"first":"Donald","last":"Trump"}}-->{"name.first":"Donald","name.last":"Trump"}【实际上ES会将其转换为以下格式,并通过Lucene存储】。
nested类型【"nested"】nested类型是特殊的对象类型,特殊的地方是索引对象数组方式不同,允许数组中的对象“各自地进行索引”【也是各个元素类型可以不一致】,目的是对象之间彼此独立被查询出来。
{n"mappings":{n"properties":{n"actors":{n"type":"nested",n"properties":{n"id":{n"type":"keyword",n"store":truen},n"name":{n"type":"keyword",n"store":truen},n"sex":{n"type":"integer",n"store":truen}n}n}n}n}n}1.2.3、多字段特性
多字段特性(multi-fields),表示允许对同一字段采用不同的配置,比如分词、text.keyword等。
常见例子是对人名实现拼音搜索,只需要在人名中新增一个字段pinyin即可。
特殊类型:地理类型、ip(记录ip地址)、completion(实现自动补全)、token_count(记录分词数)、murmur3(记录字符串hash值)。
地理类型地理类型分为两种:经纬度类型和地理区域类型,这里主要介绍经纬度类型:经纬度类型
经纬度类型自动可以存储经纬度相关信息。通过地理类型的字段,可以用来实现诸如查找在指定地理区域内相关的文档、距离某个点范围内的文档、根据地理位置修改搜索评分等需求。如果需要使用经纬度类型,需要手动定义映射。
{"mappings":{"properties":{"location":{"type":"geo_point"}}}}
geo_point(geo_point接受以下地理位置数据)
#经纬度键值对,lat为纬度,lon为经度{"location":{"lat":29.0,"lon":107.0}}#用逗号分割的字符串,前者为纬度,后者为经度{"location":"29.0,107.0"}#数组形式坐标{"location":[29.0,-50.0]}
IP类型可以用来存储IPv4或者IPV6地址,如果需要存储IP类型的字段,需要手动定义映射。
#ip类型PUTmy_index{"mappings":{"properties":{"ip_addr":{"type":"ip"}}}}PUTmy_index/_doc/1{"ip_addr":"192.168.1.1"}GETmy_index/_search{"query":{"term":{"ip_addr":"192.168.0.0/16"}}}#ip_range类型PUTrange_indexPUTrange_index/_mapping{"properties":{"ip_whitelist":{"type":"ip_range"}}}PUTrange_index/_doc/2{"ip_whitelist":"192.100.0.0/16"}PUTrange_index/_doc/3{"ip_whitelist":"192.100.100.0/24"}GET/range_index/_search{"query":{"range":{"ip_whitelist":{"gte":"192.100.0.0","lte":"192.100.88.0"}}}}
join类型join类型是ES6.x引入的类型,以取代淘汰_parent元字段。用来实现文档的一对一、一对多的关系。ES一般不用来做关系映射。
1.3、字段属性限制的是搜索、存储、聚合、排序等特性。类型
说明
_source
默认是打开的,将原始文档以JSON的形式存储在_source字段中,在lucene中_source只是一个字段,即在一个字段中存储了一个文档中所有字段的值。_source是es层面的设置,相当于给lucene多加了一个字段用于存储整个原始文档的值。不需要读取原始字段内容可以考虑关闭,但是关闭后无法reindex,无法在查询中使用script。
enabled
默认值为true,设置字段是否索引分析。false仅存储,不做搜索和聚合分析。(只在_source中存储,关闭index和doc_values操作)【不能查询、聚合,可以在_source展示】
index
默认为true,控制当前字段是否索引,是否analyze,是否加入倒排索引,关闭后无法对其进行搜索【比如:手机号、身份证号等敏感信息,不希望被检索】但字段仍存储在_source和doc_values,即字段可以被排序和聚合。【不能查询,可以聚合,在_source展示】
index_options
用于控制倒排索引记录的内容。
docs:只记录docid;freqs:记录docid和termfrequencies;positions:记录docid、termfrequencies和termposition;offsets:记录docid、termfrequencies、termposition和characteroffsets。
text类型默认配置为positions,其他默认为docs。
store
默认是false,即为不存储该字段;如果该字段的store属性设置为true,则在lucene中该字段的值被单独存储,与_source是相互独立的,同时开启会将该原始字段存储两份。【指定stored_fields才能查询store字段】
doc_values
倒排索引可以提供全文检索的能力,但是无法对排序和聚合提供支持。doc_values本质是一个序列化的列式存储。这个结构非常适用于聚合,排序。es默认几乎为所有类型提供列doc_value支持。除了analyzed类型,而text字段就是analyzed类型,如果不需要对该字段排序或聚合。则关闭该字段的doc_value存储。
field_data
默认值为false。实现聚合和排序,不过它是基于内存。
norms
默认值为true。是否需要对字段做打分操作。
dynamic
mapping级别的设置,控制字段的新增,true默认值,允许新增字段和写入;false不允许新增字段,文档可以写入,但是无法查询;strict文档不能写入。
coerce
默认是true。是否开启数据类型转换功能,比如数字类型字符串转数字。
multifields
多字段,灵活的使用多字段特性来解决多样的业务需求。
date_detection
默认是true。是否字段识别日期类型。
null_value
当字段遇到null值时的处理策略,默认为null,即空值,此时es会忽略该值。可以通过设定字段的默认值。
eager_global_ordinals
默认值为false。指明该字段是否加载全局序数?默认为false,不加载。对于经常用于术语聚合的字段,启用此功能是个好主意。
ignore_above
默认值是256,该参数的意思是,当字段文本的长度大于指定值时,不会被索引【不能搜索】,但是会存储【可以随数据一起显示】。
1.4、mapping字段设置流程不需要排序或者聚合分析功能
doc_values设定为falsefielddata设定为false1.4.4、是否需要另行存储store设定为true,即可存储该字段的原始内容(与_source中的不相关)一般情况是结合_source的enabled设定为false时使用该属性索引
索引创建后,分片不能修改,副本数可修改。二、搜索原理Elasticsearch是分布式搜索引擎,因此提供的所有功能都是分布式的。默认情况下,ES的查询分为两个阶段,“query阶段”和“fetch阶段”。
query阶段注意:
当查询from=90,size=10时,即在每个分片都有一个优先级队列,都会查询100条,然后返回10条给“协调节点”,若有5个分片,协调节点就有50条数据,然后取10条。query阶段,每个shard只返回docId和所有参与排序字段的值例如_score,在fetch阶段再通过docId查询_source里数据返回客户端。查询过程分类queryandfetch(最快的)、querythenfetch(es默认的搜索方式)、DFSqueryandfetch(精确控制搜索打分)、DFSquerythenfetch(精确控制搜索打分和排名,最慢的)从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。从搜索的准确度来说,DFS要比非DFS的准确度更高。三、搜索分类3.1、按结构分类3.1.1、URLURI搜索方式通过URI参数来指定查询相关参数。
GET/alibaba/employee/_search?q=last_name:Smith//精确wherelast_namelike'%Smith%'GET/website/_search?q=+name:trying+date:2014//wherenamelike'%trying%'ordatelike'%2014%',+前缀表示必须与查询条件匹配GET/_search//搜索所有的索引中所有的类型nGET/alibaba/_search//在alibaba索引中搜索所有的类型nGET/alibaba,kxtx/_search//在alibaba和kxtx索引中中搜索所有的文档nGET/m*,k*/_search//在任何以m或者k开头的索引中搜索所有的类型nGET/alibaba/employee/_search//在alibaba索引中搜索employee类型nGET/gb,us/user,tweet/_search//在gb和us索引中搜索user和tweet类型nGET/_all/user,tweet/_search//在所有的索引中搜索user和tweet类型nn{undefinedn"hits":{//最重要的部分n"total":14,//匹配到的文档总数n"hits":[//文档结果集n{undefinedn"_index":"us",n"_type":"tweet",n"_id":"7",n"_score":1,//它衡量了文档与查询的匹配程度,默认是按照_score降序排列的n"_source":{//原始文档n"date":"2014-09-17",n"name":"JohnSmith",n"tweet":"TheQueryDSLisreallypowerfulandflexible",n"user_id":2n}n},n...9RESULTSREMOVED...n],n"max_score":1//与查询所匹配文档的_score的最大值n},n"took":4,//整个请求耗费了多少毫秒n"_shards":{//查询中参与分片的总数n"failed":0,//正常情况下我们不希望分片失败,但是分片失败是可能发生的(遭遇到一种灾难级别的故障:丢失了相同分片的原始数据和副本)n"successful":10,n"total":10n},n"timed_out":false//查询是否超时,默认情况下,搜索请求不会超时n}3.1.2、DSL
Requestbody搜索方式以JSON格式在请求体中定义查询query。
GET/twitter/_search{"query":{"term":{"user":"kimchy"}}}
3.2、按复杂度分类注:包含URL和DSL,下面着重展示DSL。
简单查询复合查询聚合查询首层关键字
query
查询
aggs
聚合
sort
排序。可以指定按一个或多个字段排序。也可通过_score指定按评分值排序,_doc按索引顺序排序。默认是按相关性评分从高到低排序。对于值是数组或多值的字段,也可进行排序,通过mode参数指定按多值的(min/max/sum/avg/median)。
GET/bank/_search{"query":{"match_all":{}},"sort":[{"age":{"order":"desc"//如果不给定,默认是asc,_score默认是desc}},{"balance":{"order":"asc"}},"_score"]}
From/Size
分页查询,请注意,From+Size不能超过index.max_result_window索引设置,默认值为10000。
在分布式系统中,对结果排序的成本随分页的深度成指数上升。这就是web搜索引擎对任何查询都不要返回超过1000个结果的原因:假设在一个有5个主分片的索引中搜索,size=10(每一个分片产生前10的结果,返回给协调节点,协调节点对50个结果排序得到全部结果的前10个),size=10&from=10000(每个分片不得不产生前10010个结果,然后协调节点对全部50050个结果排序最后丢弃掉这些结果中的50040个结果)。要解决它,请参阅scroll或searchafterapi以获得更有效的深度滚动方法。
GET/_search{
"from":0,"size":10,"query":{"term":{"user":"kimchy"}}}
SearchAfter
在指定文档后取文档,可用于深度分页
search_after的理念是,在不同分片上(假设有5个分片),先按照指定顺序排好,根据我们传的search_after值,然后仅取这个值之后的size个文档。这5*size个文档拿到Es内存中排序后,返回前size个文档即可
GETtwitter/_search{"size":10,"query":{"match":{"title":"elasticsearch"}},"search_after":[1463538857,"654323"],"sort":[{"date":"asc"},{"_id":"desc"}]}
注意:使用search_after,必须有全局唯一id来排序(最好排序中包含_id字段)。取满足search_after值的数据,再取size条数据。
Scroll
与在传统数据库中使用光标的方式非常相似(游标查询允许我们先做查询初始化,然后再批量地拉取结果)。Scroll可以有效地执行大批量的文档查询,而又不用付出深度分页那种代价。它仅仅从还有结果的分片返回下一批结果。
游标查询会取某个时间点的快照数据,查询初始化之后索引上的任何变化会被它忽略。
深度分页的代价根源是结果集全局排序,如果去掉话查询结果的成本就会很低。游标查询用字段_doc来排序。
GET/old_index/_search?scroll=1m//保持游标查询窗口一分钟{"query":{"match_all":{}},"sort":["_doc"],//_doc是最有效的排序顺序"size":1000//仅作用于单个分片,有可能取到超过这个值数量,}{//返回结果"scroll":"1m","scroll_id":"cXVlcnlUaGVuRmV0Y2..."}_scroll_id,每次请求会返回一个新值(它是一个base64编码的长字符),每次我们做下一次游标查询,我们必须把前一次查询返回的字段_scroll_id传递进去,当没有更多的结果返回的时候才算结束
_source
对返回的_source字段进行选择
GET/_search{//或者"_source":"obj.*"或者"_source":["obj1.*","obj2.*"]"_source":{"includes":["obj1.*","obj2.*"],"excludes":["*.description"]},"query":{"term":{"user":"kimchy"}}}
Fields
指定返回哪些stored字段【没有stored字段,就不会返回】,*可用来指定返回所有存储字段,不会返回_source。
GET/_search{"stored_fields":["user","postDate"],"query":{"term":{"user":"kimchy"}}}
ScriptFields
用脚本来对命中的每个文档的字段进行运算后返回
DocvalueFields
返回存储了docValue的字段值,文档值是一种磁盘上的数据结构,以面向列的方式存储,这对于排序和聚合有效。
GET/_search{"query":{"match_all":{}},"docvalue_fields":["test1","test2"]}
Postfilter
后置过滤:在查询命中文档、完成聚合后,再对命中的文档进行过滤
{"query":{"match_all":{}},"post_filter":{//先查询再过滤"term":{"price":30}}}
还有一个对应的反向的操作,filtered(先过滤再查询,速度快),不过已废弃。filtered查询将替换为bool查询。
{"query":{"filtered":{"query":{"match":{"match_all":{}}},"filter":{"term":{"price":30}}}}}
Highlighting
高亮显示
Explain
对每次命中的分数计算方式启用解释
GET/_search{"explain":true,"query":{"term":{"user":"kimchy"}}}
Rescoring
目前,rescoreAPI只有一个实现:rescorer查询,它使用查询来调整评分。在将来,可提供替代的再订阅者,例如,成对的再订阅者。rescorer查询仅对查询和后筛选阶段返回的top-k结果执行第二个查询。每个分片上要检查的文档数可以由window_size参数控制,该参数默认为10。默认情况下,原始查询和rescorer存储查询的分数是线性组合的,以生成每个文档的最终分数。原始查询和rescorer查询的相对重要性可以分别通过查询权重和rescorer查询权重来控制。两者都默认为1。
POST/_search{"query":{"match":{"message":{"operator":"or","query":"thequickbrown"}}},"rescore":{"window_size":50,"query":{"rescore_query":{"match_phrase":{"message":{"query":"thequickbrown","slop":2}}},"query_weight":0.7,"rescore_query_weight":1.2}}}
Preference
选择在那些分片上执行查询,它有_primary、_primary_first、_replica..
Version
指定返回文档的版本字段
GET/_search{"version":true,"query":{"term":{"user":"kimchy"}}}
IndexBoost
允许在搜索多个索引时为每个索引配置不同的boostlevel。当来自一个索引的点击比来自另一个索引的点击更重要时(想想每个用户都有一个索引的社交图),这非常方便
min_score
限制最低评分得分
GET/_search{"min_score":0.5,"query":{"term":{"user":"kimchy"}}}
NamedQueries
每个过滤器和查询可以在其顶级定义中接受一个名称。
GET/_search{"query":{"bool":{//bool查询只对查询和过滤器有意义"should":[{"match":{"name.first":{"query":"shay","_name":"first"}}},{"match":{"name.last":{"query":"banon","_name":"last"}}}],"filter":{"terms":{"name.last":["banon","kimchy"],"_name":"test"}}}}}
Innerhits
父联接和嵌套功能允许返回在不同范围内具有匹配项的文档。
FieldCollapsing
用collapse指定根据某个字段对命中结果进行折叠
3.2.1、基本查询Query查询和Filter查询DSL查询分为:Query查询和Filter查询(查询(Query)和过滤(filter),查询即是之前得到的query查询,它(查询)默认会计算每个返回文档的得分,然后根据得分排序,而过滤(filter)直会筛选出符合的文档,并不计算得分,且它可以缓存文档,所以,单从性能考虑,过滤比查询更快)
Querycontext
查询上下文,用在查询上下文中的子句回答“这个文档有多匹配这个查询?”。除了决定文档是否匹配,字句匹配的文档还会计算一个子句评分,来评定文档有多匹配。查询上下文由query元素表示。
查询器有:match_all、match、multi_match、bool、wildcards、regexp、prefix、match_phrase
Filtercontext
过滤上下文,过滤上下文由filter元素或bool中的mustnot表示。用在过滤上下文中的字句回答“这个文档是否匹配这个查询?”,过滤语句的目的就是缩小匹配的文档结果集,不参与相关性评分。被频繁使用的过滤器将被ES自动缓存,来提高查询性能。
过滤器有:term、terms、range、exists、missing、bool、script、type、ids
3.2.2、复合查询复合查询模型:{n"query":{//1、查询n"bool":{//2、复合bool、boosting、constant_score、dis_max、function_scoren"must":[//3、复合关联词must、filter、should、must_notn{n"match":{//4、简单查询关键字match、range、term....n"title":"Search"//5、查询的字段n}n},n{n"match":{n"content":"Elasticsearch"n}n}n],n"filter":[n//过滤n{n"term":{n"status":"published"n}n},n{n"range":{n"publish_date":{n"gte":"2015-01-01"n}n}n}n]n}n}n}
大类
子类
说明
bool
must
包含
filter
过滤
should
可能
must_not
排除
boostingquery
positive
用来区别must、must_not组合中的must_not粗暴过滤。positive包含,negative按照negative_boost分数降低结果顺序。
就是相近的不直接排除,而是排在后面。【查询“苹果公司”,苹果树排在后面】
{"query":{"boosting":{"positive":{"match":{"content":"apple"}},"negative":{"match":{"content":"pie"}},"negative_boost":0.5}}}
negative
negative_boost
constant_score
filter
目的就是返回指定的score,一般都结合filter使用,因为filtercontext忽略score
dis_max
queries
只是取分数最高的那个query的分数而已。
GET/_search{"query":{"dis_max":{"queries":[{"term":{"title":"Quickpets"}},{"term":{"body":"Quickpets"}}],"tie_breaker":0.7}}}
function_score
function_score是处理分值计算过程的终极工具
3.2.3、聚合查询聚合查询模型{n"aggs":{//查询类型n"trigger":{//操作自定义名称n"date_histogram":{//聚合类型【Metric、Bucketing】n"field":"triggerTime",n"format":"yyyy-MM-dd"n}n}n}n}n
分类
子类
关键字
含义
例子
Metric(指标)
它对文档进行权值计算,类似sql中的统计单值分析
min
最小值
max
最大值
avg
平均值
sum
总数
cardinality
distinct聚合
多值分析
stats
min、max、sum、count、avg5个值一起输出
extended_stats
比stats多的维度:平方和、方差、标准差、平均值加/减两个标准差的区间
percentile
百分比统计
percentile_rank
百分比排名聚合
tophits
最高匹配权值聚合
geo_bounds
地理边界聚合
geo_centroid
地理重心聚合
Bucketing(桶)
它执行的是对文档分组的操作(与sql中的groupby类似)terms
词聚合(字段分组groupby)
filter
过滤聚合
filters
多过滤聚合
range
范围分组聚合(按区间分组统计count)
date_range
日期范围聚合
ip_range
【IPv4范围】的桶分聚合
missing
缺失值的桶聚合
Pipeline(管道)
聚合基础上的聚合【从其他聚合而不是文档或字段获取输入的聚合。】包含bucket_path指定上一层的路径parent父聚合
max_bucket、min_bucket、avg_bucket、thesum_bucket
{"size":0,"aggs":{"sales_per_month":{"date_histogram":{"field":"date","interval":"month"},"aggs":{"sales":{"sum":{"field":"price"}}}},"avg_monthly_sales":{"avg_bucket":{"buckets_path":"sales_per_month>sales"}}}}
stats、extended_status_bucket、percentiles_bucket
sibling兄弟聚合
derivative(求导)、cumulativesum(累计求和)、movingfunction(滑动窗口)
{"aggs":{"sales_per_month":{"date_histogram":{"field":"date","interval":"month"},"aggs":{"sales":{"sum":{"field":"price"}},"sales_deriv":{//对每个月销售总和sales求导"derivative":{"buckets_path":"sales"//用于计算均值的权值路径,同级,直接用metric值}}}}}}
Matrix(矩阵)
3.3、样例GET/1400_notification_log_202210/_searchn{n"size":1,//返回条数n"query":{n"bool":{//复合查询关键字n"must":[n{n"match_phrase":{//简单查询n"viewType":"10.117.58.88:80"n}n},n{n"range":{n"notificationTime":{n"gte":"2022-10-3100:00:00.000",n"lte":"2022-10-3123:59:59.999"n}n}n}n]n}n},n"aggs":{//聚合查询关键字n"fenzu":{n"terms":{//桶n"field":"objectType"n}n},n"distinct-objectTyp":{n"cardinality":{//指标n"field":"objectType"n}n},n"callInterfaceTimeSlot_range":{//【接口调用时间按照0~20,20~100,100以上分组统计】n"range":{n"field":"callInterfaceTimeSlot",n"ranges":[n{n"to":20n},n{n"from":20,n"to":100n},n{n"from":100n}n]n},n"aggs":{//嵌套【对每个区间】n"b_stats":{n"stats":{n"field":"callInterfaceTimeSlot"n}n}n}n},n"dataLength_statictis":{n"date_histogram":{//【抓拍接收时间,按小时分段统计】n"field":"checkTime",n"interval":"hour"n},n"aggs":{n"dataLength_sum":{n"sum":{//【计算每个分段数据总大小】n"field":"dataLength"n}n}n}n},n"avg_dataLength":{//管道【父子】n"avg_bucket":{n"buckets_path":"dataLength_statictis>dataLength_sum"//【计算总大小】n}n}n}n}n{n"took":10,n"timed_out":false,n"_shards":{n"total":5,n"successful":5,n"skipped":0,n"failed":0n},n"hits":{n"total":{n"value":1266,n"relation":"eq"n},n"max_score":1.0020769,n"hits":[],nn"aggregations":{n"dataLength_statictis":{n"buckets":[n{n"key":1667188800000,n"doc_count":318,n"dataLength_sum":{n"value":603246.0n}n},n{n"key":1667192400000,n"doc_count":360,n"dataLength_sum":{n"value":682920.0n}n},n{n"key":1667196000000,n"doc_count":360,n"dataLength_sum":{n"value":682920.0n}n},n{n"key":1667199600000,n"doc_count":222,n"dataLength_sum":{n"value":421134.0n}n}n]n},n"fenzu":{n"doc_count_error_upper_bound":0,n"sum_other_doc_count":0,n"buckets":[n{n"key":"12",n"doc_count":1260n},n{n"key":"3",n"doc_count":6n}n]n},n"distinct-objectTyp":{n"value":2n},n"callInterfaceTimeSlot_range":{n"buckets":[n{n"key":"*-20.0",n"to":20.0,n"doc_count":131,n"bmax":{n"count":131,n"min":14.0,n"max":19.0,n"avg":18.18320610687023,n"sum":2382.0n}n},n{n"key":"20.0-100.0",n"from":20.0,n"to":100.0,n"doc_count":1104,n"bmax":{n"count":1104,n"min":20.0,n"max":36.0,n"avg":22.08786231884058,n"sum":24385.0n}n},n{n"key":"100.0-*",n"from":100.0,n"doc_count":25,n"bmax":{n"count":25,n"min":868.0,n"max":1213.0,n"avg":1049.44,n"sum":26236.0n}n}n]n},n"avg_dataLength":{n"value":597555.0n}n}n}四、数据处理4.1、script:ctx._source应用
PUT/person_test/_doc/1nn{nn"name":"zhangsan",nn"age":20,nn"cards.sfz":"12121",nn"hairs":["red"],nn"createTime":1666753812000nn}查询【字段修饰】
GET/person_test/_searchn{n"script_fields":{n"result":{n"script":{n"source":"doc['age'].value*params['multiplier']",n"params":{"multiplier":2}n}n}n}n}n结果:n{n"_index":"person_test",n"_type":"_doc",n"_id":"1",n"_score":1.0,n"fields":{n"result":[n40n]n}n}内容更新【多字段更新、传参更新、判断更新、查询更新】
//传参更新nPOST/person_test/_update/1n{n"script":{n"source":"ctx._source.age+=params.count",n"lang":"painless",n"params":{n"count":4n}n}n}n结果:age=24nn//数组添加元素nPOST/person_test/_update/1n{n"script":{n"source":"ctx._source.hairs.add(params.hair)",n"lang":"painless",n"params":{n"hair":"blue"n}n}n}n结果:hairs=red、bluenn//判断更新nPOST/person_test/_update/1n{n"script":{n"source":"if(ctx._source.hairs.contains(params.tag)){ctx.op='delete'}else{ctx.op='none'}",n"lang":"painless",n"params":{n"tag":"blue"n}n}n}nn//多字段更新【简写】nPOST/person_test/_update/1n{n"script":"ctx._source.age=20;ctx._source.name+='程飞'"n}匹配插入
POST/person_test/_update_by_queryn{n"script":{n"lang":"painless",n"source":"ctx._source.name=params.par"n,"params":{n"par":"程飞"n}n},n"upsert":{n"name":"wangwu",n"age":30n}n}n结果:插入新数据新增字段
POST/person_test/6/_updaten{n"script":"ctx._source.new_field='value_of_new_field'"n}nn结果n{n"_index":"person",n"_id":"6",n"_version":4,n"found":true,n"_source":{n"name":"zhangsan",n"age":24,n"cards.sfz":"12121",n"hairs":[n"red",n"blue"n],n"new_field":"value_of_new_field"n}n}删除字段
POST/person_test/_update_by_queryn{n"script":"ctx._source.remove('cards.sfz')",n"query":{n"bool":{n"must":[n{n"exists":{n"field":"cards.sfz"n}n}n]n}n}n}n结果:_source中无cards.sfz字段4.2、分页
//fromsizenGET/test_student_new/_searchn{n"query":{n"bool":{n"must":[n{"match":{n"grade":"初二"n}}n]n}n},n"sort":[n{n"id":{n"order":"asc"n}n}n],n"from":0,n"size":3n}nn//search_afternGETtest_student_new/_searchn{n"query":{n"bool":{n"must":[n{"match":{n"grade":"初二"n}}n]n}n},n"sort":[n{n"id":{n"order":"asc"n}n}n],n"size":2,n"search_after":[n3n]n}nn//scrollnPOSTtest_student_new/_search?scroll=1mn{n"size":2,n"query":{n"match_all":{nn}n}n}nnPOST/_search/scrolln{n"scroll":"1m",n"scroll_id":"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAxETQWdzZhZWdPWlFRQW1kRkpaQkxjNU9PUQ=="n}4.3、排序
#n#1、创建新索引nPUTstudent_test_newn{n"mappings":{n"properties":{n"age":{n"type":"long"n},n"bir":{n"type":"date"n},n"bri":{n"type":"date"n},n"grade":{n"type":"text",n"fields":{n"keyword":{n"type":"keyword",n"ignore_above":256n}n}n},n"id":{n"type":"long"n},n"name":{n"type":"text",n"fields":{n"keyword":{n"type":"keyword",n"ignore_above":256n}n}n},n"nation":{n"type":"text"n}n}n}n}nn//2、数据同步nPOST_reindexn{n"source":{n"index":"student_test"n},n"dest":{n"index":"student_test_new"n}n}4.5、rollover为索引添加alias是别名,别名绑定_rollver,手动执行_rollver满足条件后可以创建新索引【是执行_rollver创建索引,不是插入数据】、【_ilm/policy自动执行默认是10分钟】。_rollver滚动索引时,要求创建索引以数字结尾,最多6位,滚动时,会在数字上加1,默认是000001这6位数字。当我们在ILM中开启了rollover后,流转到下一节点的min_age是在rollover触发后才开始计时的。当别名关联索引时【一对多】:通过索引【test_xxxxxx】随时可以写数据。但是通过别名【test_alais】,只有关联的索引【test_000001】是is_write_index,才能通过别名【test_alais】插入数据。同一个索引【test】的滚动【test_000001、test_000002】,默认只有一个is_write_index为true的索引【test_000002】,就是别名【test_alais】只能写到这个索引中【test_000002】。当索引添加别名时【一对多】:当添加的别名【test_alais1】设置了is_write_index属性,原别名【test_alais】会继续与索引关联,如果没有is_write_index属性,原别名【test_alais】就会与该索引解除关联,也就是通过原别名不能查询该索引的数据。
//创建模板【创建setting、mapping关联alais、ilm(rollover)】【_template---alais---rollover---data】nPUT_template/student_test_templaten{n"index_patterns":"student_test-*",//匹配索引的规则n"order":1,n"settings":{n"number_of_shards":4,n"number_of_replicas":1,n"lifecycle":{n"name":"student_test_ilm_policy",//ilmn"rollover_alias":"alias_student_test_rollover"//aliasn}n},n"mappings":{n"properties":{n"name":{n"type":"keyword"n},n"age":{n"type":"long"n},n"birthday":{n"type":"date",n"format":"yyyy-MM-ddHH:mm:ss||yyyy-MM-dd||epoch_millis"n}n}n},n"aliases":{n"alias_student_test_rollover":{n"is_write_index":truen}n}n}nnn==_ilm【自动_rollover】============================================================nn//设置_ilm【自动滚动】nPUT/_ilm/policy/student_test_ilm_policyn{n"policy":{n"phases":{n"hot":{n"min_age":"0ms",n"actions":{n"rollover":{n"max_age":"30d",n"max_size":"100gb",n"max_docs":3n}n}n},n"delete":{n"min_age":"120d",n"actions":{n"delete":{}n}n}n}n}n}nn//添加数据【“别名”或者student_test-000001要包含后缀】nPOST/alias_student_test_rollover/_doc/5n{n"name":"zhangsan5",n"age":21,n"birthday":1666753812000n}nnGET/alias_student_test_rollover/_searchnnGET/alias_student_test_rollover/_aliasnnGET/_ilm/policynnn==手动_rollover============================================================n//添加aliasesnPUTstudent_test-000001n{n"aliases":{n"alias_student_test_read":{n"is_write_index":truen}n}n}nn//添加_rollover【手动滚动,执行此句时,当满足条件就会创建新索引,创建索引是执行此触发的,插入数据,就会插入新索引】nPOST/alias_student_test_read/_rollovern{n"conditions":{n"max_docs":2,n"max_age":"30d",n"max_size":"500gb"n}n}nnPOST/alias_student_test_read/_doc/12n{n"name":"lisi12",n"age":21,n"birthday":1666753812000n}nnnGET/alias_student_test_read/_search
显示全部
收起
最新更新 | 文章排行 | 滇ICP备2023006777号 | 网站地图