文章目录
1、基本概念
Elasticserach与数据库类似,将其于Mysql对比如下
- Index -> 数据库
- type -> table表
- document -> row 行
- field -> columns列
- mapping—>表结构
详细说明:
概念 | 说明 |
---|---|
索引库(indices) | indices是index的复数,代表许多的索引 |
类型(type) | 类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引,比如商品索引,订单索引,其数据格式不同。不过这会导致索引库混乱,因此未来版本中会移除这个概念 |
文档(document) | 存入索引库原始的数据。比如每一条商品信息,就是一个文档 |
字段(field) | 文档中的属性 |
映射配置(mappings) | 字段的数据类型、属性、是否索引、是否存储等特性 |
2、基本操作
2.1 安装
7.8.1 es & kibana
elasticsearch.yml
cluster.name: my-application
node.name: node-1
kibana.yml
server.host: "0.0.0.0"
elasticsearch.hosts: "http://localhost:9200/"
kibana启动非常慢,启后打开:
http://localhost:5601/
进入到DevTools ,可以执行es命令
2.2、kibana下的基本操作:
# 创建索引
put enjoy_test
#获取索引
get enjoy_test
结果:
{
"enjoy_test" : {
"aliases" : { },
"mappings" : {
"properties" : {
"msg" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1596175971739",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "CqPBlfUFR4ineIZAl9yhQw",
"version" : {
"created" : "7080199"
},
"provided_name" : "enjoy_test"
}
}
}
}
#在索引下新增文档
put enjoy_test/_doc/1
{
"msg":"hello world!"
}
#结果:
{
"_index" : "enjoy_test",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
#获取指定Id 索引下的文档
get enjoy_test/_doc/1
结果:
{
"_index" : "enjoy_test",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"msg" : "hello world!"
}
}
#获取索引映射
# 创建索引不指定mapping, 插入数据后,会自动给字段加上多字段类型,text和keyword类型
get enjoy_test/_mapping
{
"enjoy_test" : {
"mappings" : {
"properties" : {
"msg" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
#指定mappings,创建索引:
#先创建索引
put /open-soft
#然后 设置mapping
put /open-soft/_mapping
{
"properties":{
"corp":{
"type":"text"
},
"lang":{
"type":"text"
},
"name":{
"type":"text"
}
}
}
# 新增文档
put /open-soft/_doc/1
{
"name": "Apache Hadoop",
"lang": "Java",
"corp": "Apache",
"stars":200 #多加这一个字段
}
#再看看它的mapping:
get open-soft/_mapping
结果:es自动帮我们添加这个字段的类型为long
{
"open-soft" : {
"mappings" : {
"properties" : {
"corp" : {
"type" : "text"
},
"lang" : {
"type" : "text"
},
"name" : {
"type" : "text"
},
"stars" : {
"type" : "long"
}
}
}
}
}
# 一个字段被设置为基本类型,那么天生支持数组,可以添加如下:
put /open-soft/_doc/1
{
"name": "Apache Hadoop",
"lang": ["Java","php"],#添加多个,这样加就可以了
"corp": "Apache",
"stars":[500,200]#添加多个,这样加就可以了
}
#对象类型:字段中还可以包含文档,放入id为object的文档
put /open-soft/_doc/object
{
"name": ["Apache ShardingSphere"],
"lang": "Java",
"corp": "JingDong",
"stars":400,
"address":
{ "city":"BeiJing",#这个字段中,又包含了文档
"country":"亦庄"
}
}
#查看这个索引的mapping: 只取了部分,address字段中,有city 和contry2个属性,它们分别有自己的类型
"address" : {
"properties" : {
"city" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"country" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
#索引字段 支持多数据类型,也就是说我可以将一个字段定义为多种数据类型,比如:一个字符串类型的字段,可以使用 text 类型做全文检索,使用 keyword 类型做聚合和排序
2.3字段参数analyzer分启器
analyzer 该参数可以在每个查询、每个字段、每个索引中使用,其优先级如 下(越靠前越优先):
1、字段上定义的分词器
2、索引配置中定义的分词器
3、默认分词器(standard)
自定义analyzer:
PUT index
{
"settings": {
"analysis": {
"normalizer": {
"my_normalizer": { //1
"type": "custom",
"char_filter": [],
"filter": ["lowercase", "asciifolding"] //2
}
}
}
},
"mappings": {
"properties":{
"foo": {
"type": "keyword",
"normalizer": "my_normalizer" //3
}
}
}
}
代码 1:首先在 settings 中的 analysis 属性中定义 normalizer。
代码 2:设置标准化过滤器,示例中的处理器为小写、asciifolding。
代码 3:在定义映射时,如果字段类型为 keyword,可以使用 normalizer
3、es索引管理
3.1、索引管理
1、列出所有索引
GET /_cat/indices?v
2、关闭和打开索引
POST /open-soft/_close
POST /open-soft/_open
3、配置索引
通过 settings 参数配置索引,索引的所有配置项都以“index”开头。索引的 管理分为静态设置和动态设置两种。
静态设置
只能在索引创建时或在状态为 closed index(闭合索引)上设置,主要配置 索引主分片、压缩编码、路由等相关信息
put test1
{
"settings":{
"index.number_of_shards":3,
"index.codec":"best_compression"
}
}
动态设置
通过接口“_settings”进行,同时查询配置也通过这个接口进行,比如:
get _settings
get /open-soft/_settings
get /open-soft,test1/_settings
配置索引则通过:
put test1/_settings
{
"refresh_interval":"2s"
}
映射配置
通过_mapping 接口进行
get /open-soft/_mapping
4、数据检索和分析
4.1 _search接口
添加测试数据
# 查询所有数据
get kibana_sample_data_flights/_search
{
"query":{
"match_all":{}
}
}
1、from and to
get kibana_sample_data_flights/_search
{
"from":100,
"size":20,
"query":{
"match_all":{}
}
}
Elasticsearch 在使用 from 和 size 处理分页问题时会将所有数据 全部取出来,然后再截取用户指定范围的数据返回。所以在查询非常靠后的数据 时,即使使用了 from 和 size 定义的分页机制依然有内存溢出的可能,而 max_ result_ window 设置的 10000 条则是对 Elastiesearch 的一.种保护机制。
2、_source 参数
返回_source 指定的字段,如果source没有指定,返回匹配文档的元数据:_ id、_type、_index 和_score
get kibana_sample_data_flights/_search
{
"from":100,
"size":20,
"query":{
"match_all":{}
} ,
"_source":["FlightNum","DestCountry"]
}
还可以使用通配符
get kibana_sample_data_flights/_search
{
"from":100,
"size":20,
"query":{
"match_all":{}
} ,
"_source":["Origin*","*Weather"]
}
排除不需要返回的属性:
get kibana_sample_data_flights/_search
{
"query":{
"match_all":{}
} ,
"_source":{
"includes":["*lon","*.lat"],
"excludes":["DestLocation.*"]
}
}
排序:
get kibana_sample_data_flights/_search
{
"query":{
"match_all":{}
} ,
"_source":{
"includes":["*lon","*.lat"],
"excludes":["DestLocation.*"]
},
"sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
}
5、检索
5.1 基于词项搜索
term 查询—精确查询,数值,日期–类似sql =
词条查询不会分析(analyze)查询字符串
get kibana_sample_data_flights/_search
{ "query":{ "term":{ "dayOfWeek":3 } } }
terms -----sql in
get kibana_sample_data_flights/_search
{
"query":{
"terms":{
"dayOfWeek":[3,4]
}
}
}
terms 跨索引查询:
# 查询 atticeles索引中,article_id 在 索引 users里面 id=1 的articles字段值
POST /articles/_search
{
"query": {
"terms": {
"article_id": {
"index" : "users",
"id":"1",
"path":"articles"
}
}
}
}
#需要创建索引:
put users
#新加记录:
put users/_doc/1
{
"id":1,
"articles":"qqqq"
}
put users/_doc/2
{
"id":1,
"articles":"aaaa"
}
#创建索引:
put articles
#增加记录
put /articles/_doc/aaaa
{
"content":"1222222",
"article_id":"aaaa"
}
put /articles/_doc/qqqq
{
"content":"12222223333",
"article_id":"qqqq"
}
#测试
get /articles/_search
#最后关联查询
POST /articles/_search
{
"query": {
"terms": {
"article_id": {
"index" : "users",
"id":"1",
"path":"articles"
}
}
}
}
#结果
range查询和exists查询
get kibana_sample_data_flights/_search
{
"query":{
"range":{
"FlightDelayMin":{
"gte":100,
"lte":200
}
}
} ,
"_source":{
"includes":["*lon","*.lat"]
},
"sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
}
prefix查询
根据给定的前缀查询
get kibana_sample_data_flights/_search
{
"query":{
"prefix":{
"DestCountry":"D"
}
} ,
"_source":{
"includes":["DestCountry","*.lat"]
},
"sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
}
wildcard 查询和 regexp 查询
wildcard 查询就是通配符查询。
get kibana_sample_data_flights/_search
{
"query":{
"wildcard":{
"Dest":"*Marco*"
}
} ,
"_source":{
"includes":["Dest"]
},
"sort":[{"DistanceKilometers":"asc"},{"FlightNum":"desc"}]
}
6、文本分析
6.1、文本分析概念
分析( analysis )是在文档被发送并加入倒排索引之前,Elasticsearch 在其主体 上进行的操作。在文档被加入索引之前,Elasticsearch 让每个被分析字段经过一 系列的处理步骤。
■字符过滤–使用字符过滤器转变字符。
■文本切分为分词—将文本切分为单个或多个分词。
■分词过滤—使用分词过滤器转变每个分词。
■分词索引–将这些分词存储到索引中。
6.2、字符过滤
Elasticsearch 首先运行字符过滤器(char filter)。这些过滤器将特定的字符 序列转变为其他的字符序列。这个可以用于将 HTML 从文本中剥离,或者是将任 意数量的字符转化为其他字符(也许是将“I love u 2”这种缩写的短消息纠正为“I love you too”。 在“I like ELK……”的例子里使用特定的过滤器将“&” 替换为“and”。
6.3、切分为分词
6.4、分词过滤器
最为有用的和常用的分词过滤器是小写分词过滤器,它 将输人的分词变为小写,确保在搜索词条“nosql" 的时候,可以发现关于“NoSq" 的聚会。分词可以经过多于 1 个的分词过滤器,每个过滤器对分词进行不同的操 作,将数据塑造为最佳的形式,便于之后的索引。
6.5、分析器
一个分析器( analyzer ),它可以定义为零个或多 个字符过滤器、1 个分词器、零个或多个分词过滤器。Elasticsearch 中提供了很 多预定义的分析器。我们可以直接使用它们而无须构建自己的分析器。
6.6、配置分析器
可以使用_analyze API 来测试 analyzer 如何解析我们的字符串的
_analyze 接口
GET /_analyze
POST /_analyze
GET /<index>/_analyze
POST /<index>/_analyze
1、文本分词会在哪些地方用到
一般在2个地方用到, 1 创建索引,文档类型为text类型,会对该字段分词. 2 对一个text类型字段进行全文检索时会对 查询的文本进行分词.
2、分词器顺序
字段配置了优先
其设置了analysis.analyzer.default,则使用该设置的分词器;
果上面两个都未设置,则使用默认的 standard 分词器。
设置默认分词器
PUT test
{
"settings": {
"analysis": {
"analyzer": {
"default":{
"type":"simple"
}
}
}
}
}
还可以为索引配置内置分词器,并修改内置的部分选项修改它的行为:
并为字段指定内置分词器
put test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer":{
"type":"standard",
"stopwords":["the","a","an","this","is","y"]
}
}
}
} ,
"mappings":{
"properties" : {
"title" :{
"type":"text",
"analyzer":"standard",
"search_analyzer":"simple"
}
}
}
}
自定义分词器
put test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer":{
"type":"standard",
"stopwords":["the","a","an","this","is","y"]
}
}
}
} ,
"mappings":{
"properties" : {
"title" :{
"type":"text",
"analyzer":"standard",
"fields":{
"english": {
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
}
}
测试
POST /test/_analyze
{
"field": "my_text",
"text": "The old brown cow"
}
3、自定义字符过滤器
PUT pattern_test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer":{
"tokenizer":"keyword",
"char_filter":["my_char_filter"]
}
},
"char_filter":{
"my_char_filter":{
"type":"mapping",
"mappings":["test => 666","byby => 888"]
}
}
}
}
}
# 测试
POST pattern_test/_analyze
{
"analyzer": "my_analyzer",
"text": " test ,测试 byby 了"
}
4、自定义分词器
5、分词过滤器
6、自定义分析器
PUT pattern_custom
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": { //定义自己的分析器
"char_filter": [ "html_strip", "&_to_and" ],//字符过滤器2个,&_to_and是自定义的,html_strip是内置的
"filter": [ "lowercase", "my_stopwords" ],//分词过滤器2个,lowercase是内置的,my_sopwords是自定义的
"tokenizer": "standard", //分词器
"type": "custom"
}
},
"char_filter": { //这里定义自定义的字符过滤器
"&_to_and": {
"mappings": [ "&=>and" ],
"type": "mapping"
}
},
"filter": { //这里定义了自定义分词过滤器
"my_stopwords": {
"stopwords": [ "test", "test111" ],
"type": "stop"
}
}
}
}
}
#测试
POST pattern_custom/_analyze
{
"analyzer": "my_analyzer",
"text": "<br> I & test & & are handsome<br>"
}
7、基于全文的搜索
7.1、match 查询
match查询的文本 会被分词,然后用分词的 文本去检索
"query":{ "match":{ "elk":"Elasticsearch LogStash Kibana" }
分词后得到:
if( doc. elk.contains(elasticsearch) ||doc. elk.contains(logstash) ||doc. elk.contains (kibana) )
匹配查询的行为受到两个参数的控制:
operator:表示单个字段如何匹配查询条件的分词
minimum_should_match:表示字段匹配的数量
operator默认为or, 如果设置成and,那么如下:
if( doc. elk.contains(elasticsearch) &&doc. elk.contains(logstash) &&doc. elk.contains (kibana) )
对于 minimum_should_match 属性值,默认值是 1,如果设置其值为 2,表 示分词必须匹配查询条件的数量为 2,这意味着,只要文档的 elk 字段包含任意
两个关键字,就满足查询条件
7.2、multi_match 查询
POST /kibana_sample_data_flights/_search
{
"query": {
"multi_match": {
"query":"AT",
"fields":["DestCountry", "OriginCountry"]
}
}
}
请求将同时检索文档中 DestCountry 和 OriginCountry 这两个字段,只要有一 个字段包含 AT 词项该文档就满足查询条件。
7.3、match_phrase查询
精确短语匹配,查询的短语必须全部匹配才能查到
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": "query test one"
}
}
}
短语匹配使用 slop 参数来引入一些灵活性:
GET /articles/_search
{
"query": {
"match_phrase": {
"title": {
"query":"quick fox",
"slop":1
}
}
}
}
slop 参数缺省为 0,它告诉 match_phrase 查询词条能够最远相隔多远时仍然 将文档视为匹配。
7.4、match_phrase_prefix 查询
被称为基于前缀的短语匹配,比如:
GET /articles/_search
{
"query": {
"match_phrase_prefix": {
"title": {
"query":"quick fox",
"slop":1
}
}
}
}
8、模糊查询、纠错与提示器
8.1、模糊查询–fuzzy
返回包含与搜索字词相似的字词文档;为了找到相似的术语,fuzzy 查询将 在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。查询然后返回每 个扩展的完全匹配。
GET /articles/_search
{
"query": {
"fuzzy": {
"content": {
"value":"1222223",
"fuzziness":"1" //设置编辑距离为1,索引中只有content为1222222的数据,设置编辑距离为1后,可以差异为1的也找出来
}
}
}
}
fuzziness,选填项,匹配允许的最大编辑距离;可以被设置为“0”, “1”, “2”或“auto”。“auto”是推荐的选项,它会根据查询词的长度定义距离。
8.2、纠错与提示器
纠错是在用户提交了错误的词项时给出正确词项的提示,
而输入提示则是在 用户输人关键字时给出智能提示,甚至可以将用户未输人完的内容自动补全。
es提供了3种内置提示器
1、term 提示器
2、phrase 提示器
3、completion 提示器
如果要实现completion 提示器,那么在插入文档的时候 需要指定补全字段
#创建索引
PUT articles
{
"mappings":{
"properties": {
"author":{
"type": "keyword"
},
"content":{
"type": "text"
},
"suggestions":{ //设置提示器类型
"type": "completion"
}
}
}
}
#新增文档,时新增提示词
POST articles/_doc/
{
"author":"taylor",
"content":"an introduction of elastic stack and elasticsearch",
"suggestions":{
"input":["elastic stack", "elasticsearch"],
"weight":10
}
}
# 新增文档时 新增提示词
POST articles/_doc/
{
"author":"taylor",
"content":"an introduction of elastic stack and elasticsearch",
"suggestions":[
{"input":"elasticsearch", "weight":30},
{"input":"elastic stack", "weight":1}
]
}
#测试
POST articles/_search
{
"_source":"suggest",
"suggest" :{
"article_suggestion": {
"prefix": "ela", //搜索关键字
"completion": {
"field": "suggestions" //补全的匹配字段
}
}
}
}
9、组合查询与相关度组合
9.1、bool组合查询
bool将一组bool类型的子句组合起来,一些子句决定文档是否作为结果返回,一些子句不决文档是否作为结果返回,但会影响结果的相关度。
bool组合子句有:must filter should must_not 四种。
must:查询结果必须要包含的内容,影响相关度。
filter:查询结果中必须包含的内容,不会影响相关度
should:查询结果非必须包含项,如果包含了会提高分数,影响相关度
must_not 查询结果中不能包含的内容,不会影响相关度
相关度越高,排序结果会越靠前。fIlter和must_not单纯只用于过滤文档,对文档相关度没有影响,也就是说这2种子句对结果的排序没有作用。
当should子句与must 或 filter 子句同时出现在子句中时,should子句不会过滤结果,即使文档不满足should子句条件 也会返回。
POST /kibana_sample_data_logs/_search
{
"query": {
"bool": {
#只有 message 字段包含 firefox 词项的日志文档才会被返回
"must":[ {"match": { "message": "firefox"} }
],
#should子句只影响文档相关度,即使文档不满足should条件也会返回
"should":[
{"term": { "geo. src": "CN"}},
{"term": { "geo. dest": "CN"}}
]
}
}
}
如果上面句子,只有should ,那么 should 子句就至少要满足有 一条。should 子句需要满足的个数由query的minimum_ should_match参数决定, 默认情况下它的值为 1。。由于 filter 和 must_not 不参与分值运算,所以文档的最后得分是 must 和 should 子句的相 关性分值相加后返回给用户
POST /kibana_sample_data_logs/_search
{
"query": {
"bool": {
//参与过滤,影响相关度
"must":[ {"match": { "message": "firefox"} }
],
//不参与过滤,只影响相关度
"should":[
{"term": { "geo. src": "CN"}},
{"term": { "geo. dest": "CN"}}
],
//参与过滤,影响相关度
"filter":{
"term":{
"extension":"zip"
}
}
}
}
}
9.2 dis_max 组合查询
dis_max 查询也是种组合查询,会在子查询中取最大相关性分值为最终相关 性分值结果,而忽略其他子查询的相关性得分。dis_max 查询通过 queries 参数 接收对象的数组
POST /kibana_sample_data_logs/_search
{
"query":{
"dis_max":{
"queries": [
#取子句中相关性分值最大值 为最终相关分值
{"match": {"message": "firefox"} } ,
{"term": {"geo. src": "CN"} },
{"term": {"geo. dest": "CN"} }
]
}
}
}
POST /kibana_sample_data_logs/_search
{
"query":{
"dis_max":{
"queries": [
{"match": {"message": "110.47.202.158"} } ,
{"term": {"geo.src": "CN"} },
{"term": {"geo.dest": "CL"} }
],
"tie_breaker":0.7
}
}
}
在多数情况下,完全不考虑其他字段的相关度可能并不合适,所以可以使用 tie_ breaker 参数设置其他字段参与相关度运算的系数。这个系数会在运算最终 相关度时乘以其他字段的相关度,再加上最大得分就得到最终的相关度了。所以 一般来说,tie_ breaker 应该小于 1,默认值为 0。例如在示例的返回结果中,即使 文档 message 和 geo 字段都满足查询条件它也不定会排在最前面。
9.3、constant_score 查询
constant_score 查询返回结果中文档的相关度为固定值,这个固定值由 boost 参数设置,默认值为 1.0。
constant score 查询只有两个参数 filter 和 boost, filter 仅用于过滤结果而不影响分值。
POST /kibana_sample_data_logs/_search
{
"query":{
"constant_score":{
"filter":{
"match":{"geo.src": "CN" }
},
"boost": 1.3
}
}
}
9.4、boosting 查询
boosting 查询通过 positive 子句设置满足条件的文档,只有满足 positive 条件的文档才会被返回。
boosting 查询通过 negative 子句设置需要排除文档的条件,但boosting 查询不会将满足 negative 条件的文档从 返回结果中排除,而只是会拉低它们的相关性。
POST /kibana_sample_data_logs/_search
{
"query": {
"boosting": {
"positive": {"term": { "geo.src": "CN"} },
"negative": {"term":{"geo.dest": "ID"} },
#当满足 negative 条件时 相关度会乘以这个系数作为最终分值
"negative_boost": 0.2 }
},
"sort": [{"_score": "desc"}]
}
9.5、function_score 查询
function_score查询提供了一组计算查询结果 相关度的函数,通过查询条件定义不同 打分函数 , 实现自定义打分机制。查询条件通过function_score的query参数设置,而使用的打分函数则使用functions参数设置。
POST /kibana_sample_data_logs/_search
{
"query": {
"function_score":{
"query": {
"query_string": {
"fields": [ "message"],
"query": "(firefox 6.0a1) OR (chrome 11.0.696.50)"
}
},
#定义2个打分函数
"functions":[
# weight 函数会以指定的值为相关性分值
{"weight": 2 },
#random_score 函数会在 0-1 之间产生一个随机数
{"random_score": { } }
],
#score_mode 参数设置的值为 max,即从所有评分函数运算结果中取最大值。multiply、sum、avg、first、 max、min
"score_mode": "max",
//表示 query查询条件的相关评分与 打分函数运算的相关评分组合方式,avg:表示取2者的平均值
"boost_mode": "avg"
}
}
}
打分函数运算的相关性评分会与query参数中查询条件的相关度评分组合起来。组合的方式参过boost_mode参数指定,它的默认值与score_mode一样都是multiply。boost_mode参数可选值与score_mode也基本一致,但没有first而多了一个replace,代表命名用评分函数计算结果代替查询分值
9.5.1、field_value_factor 函数
field_value_factor 函数在计算相关度时允许加入某一字段作为干扰因子
POST /kibana_sample_data_logs/_search
{
"query": {
"function_score":{
"query": {
"bool": {
"must": [
{"match": { "OriginCountry": "CN"} },
{"match": { "DestCountry": "US"} }
]
}
},
#field_value_factor 打分函数通过 field 参数设置了干扰字段为 AvgTicketPrice
"field_value_factor":{
"field": "AvgTicketPrice",
#factor 则是为干扰字段设置的调整因子,它会与字段值相乘后 再参与接下来的运算
"factor": 0.001 ,
#它代表了干扰字段与调整因子相乘的结果如何参与 相关度运算,reciprocal:代表取倒数 1/x。
"modifier": "reciprocal",
#Missing 表示如果字段值是丢失的,默认被使用的值。
"missing":1000
}
}
}
}
9.5.1、衰减 函数
衰减 函数 有:高斯函数 gauss、线性函数 linear 和指数函数 exp
衰减函数:是通过递减方式计算相关度的函数,它们会从指定的原始点开 始对相关度做衰减,离原始点距离越远相关度就越低。衰减函数中的原始点是指 某字段的具体值,由于要计算其他文档与该字段值的距离,所以要求衰减函数原 始点的字段类型必须是数值、日期或地理坐标中的一种。
POST kibana_sample_data_flights/_search
{
"query": {
"function_score": {
"query": {
"match":{"OriginCityName": "Beijing" }
},
#衰减函数为高斯函数
"gauss": {
#定义原始点使用的字段为 timestmp,
"timestamp": {
#具体的原始点则通过 origin 参数定义在了 2019 年 3 月 25 日
"origin": "2019-03-25",
"scale": "7d",
#offset 参教定义 了在 1 天的范围内相关度不衰减
"offset": "1d",
#scale 参数和 decay 参数则共同决定了衰减的程度,前者定义了衰减的跨度范围, 而后者则定义了衰减多少。7d,0.3代表: 7 天后的文档相 关度衰减至 0.3 倍
"decay": 0.3
}
}
}
}
}
比如:2019年3月25日 系统有问题,24日以前,26日以后我日志我不关注,所以这段时间的相关性评分要打低,这就是衰减函数的作用。
比如:地理坐标,地图找周边,10公里以内的 餐馆 相关性越高,用衰减函数来说 就是10公里以内的相关度比较高,但越过10公里 相关度大大降低。
10、单查询条件下的相关度组合
组合查询一般由多个查询条件组成,所以在计算相关度时都要考虑以何种方 式组合相关度。而很多的查询都只针对一个字段设置查询条件,所以只有相关度 权重提升问题而没有相关度组合问题。
但有些查询,比如 multi_match 查询可以 针对多个字段设置相同的查询条件,所以它们在计算相关度时也需要考虑组合多个相关 度的问题。
multi_match 查询具有一个 type 参数,用于指定针对多字段检索时的执行逻 辑及相关度组合方法。type 参数有 5 个可选值,即 best_fields、 most_fields、 cross_ fields、phrase 和 phrase_preix。
POST /kibana_sample_data_flights/_search
{
"query":{
#查询字段originCountry或DestCountry 等于 'CN'的文档
"multi_match" :{
"query": "CN",
"fields": [ "originCountry^2","DestCountry"],
//设置2个字段 相关评分组合方式
"type": "best_fields"
}
}
}
type有5种类型:即 best_fields、 most_fields、 cross_ fields、phrase 和 phrase_preix。
10.1、best_fields、phrase 与 phrase_prefix 类型
best_fields 类型在执行时会将与字段匹配的文档都检索出来,但在计算相关 度时会取得分最高的作为整个查询的相关度。
过"OrignCountny^2"的形式将 OriginCountry 字 段的相关度权重提升到 2,所以这个字段相关度会高于 DestCountry 字段。
使用场景:
检索文章正文和标题出现的关键字,如果在标题中出现了该关键字相并度就要高于内正文出现该关键字。
在相关度计算上 dis_max 查询是不是与 best_fields 类型很像,(dis_max 查询在计算相关性分值时, 会在子查询中取最大相关性分值为最终相关性分值结果,而忽略其他子查询的相 关性得分)。best_fields 类型的查询在执行时会转化为 dis_max 查询,如下:
POST /kibana_sample_data_flights/_search
{
"query":{
"dis_max": {
"queries":[
{"match": {"OriginCountry": {"query":"CN", "boost": 2 } } }, {"match": {"DestCountry": "CN"} }
]
}
}
}
dis_max 有一个参数 tie_breaker, 可以设置非最高值相关度参与最终相关度 运算的系数,multi_match 中使用 best_fields 类型时也可以使用这个参数。 phrase 与 phrase_ prefix 类型在执行逻辑上与 best_fields 完全相同,只是在 转换为 dis_max 时 queries 查询中的子查询会使用 phrase 或 phrse_prefix 而不是 match。
10.2、most_fields 类型
most_fields 类型在计算相关度时会将所有相关度累加起来,然后再除以相关 度的个数以用到它们的平均值作为最终的相关度。
POST /kibana_sample_data_flights/_search
{
"query":{
"multi_match" :{
"query": "CN",
"fields": [ "originCountry^2","DestCountry"],
"type": "most_fields"
}
}
}
它会将 OriginCountry 和 DestCountry 两个字段匹配 CN 时计算出的相关度累 加,然后再用累加和除以 2 作为最终的相关度。所以只有当两个字段都匹配了 CN,最终的相关度才会更高。这在效果上相当于将出发地和目的地都是中国的 文档排在了最前面,所以适用于希望检索出多个字段中同时都包含相同词项的检 索。在实现上,most_fields 类型的查询会被转化为 bool 查询的 should 子句,上 面的示例实际被转化为:
POST /kibana_sample_data_flights/_search
{
"query":{
"bool": {
"should":[
{"match": {"OriginCountry": {"query":"CN", "boost": 2 } } }, {"match": {"DestCountry": "CN"} }
]
}
}
}
10.3、cross_fields 类型
如果查询条件中设置了多个词项,best_fields 类型和 most_ fields 类型都支 持通过 operator 参数设置词项之间的逻辑关系,即 and 和 or。 但它们在设置 operator 时是针对字段级别的而不是针对词项级别的,
POST /kibana_sample_data_logs/_search
{
"query":{
"multi_match" :{
"query": "firefox success",
"fields": ["message", "tags"],
"type": "best_fields",
"operator": "and"
}
}
}
operator:and , type:best_fields 下 表示 message tags 2个字段必须都包含 “firefox success”,这样的文档不存在。
而在 cross_fields 类型则可以理解为将文档的中 message 和 tags 字段组合为 一个大的字段,然后在大的字段中搜索词条 firefox 和 success。这样的话只要 firefox 和 success 在大字段中均出现过,就认为这个文档符合条件。
这样就会查询到值。
POST /kibana_sample_data_logs/_search
{
"query":{
"multi_match" :{
"query": "firefox success",
"fields": ["message", "tags"],
"type": "cross_fields",
"operator": "and"
}
}
}
11、聚集查询
聚集查询 提供了多条文档的统计功能运算,如同mysql中的avg函数等 功能。
聚集类型总体上被分为四种大类型,即指标聚集(Metrics Aggregation)、 桶 型( Bucket Aggregation)、管道聚集( Pipeline Aggregation) 和矩阵聚集( Matrix Aggregation)。
- 指标聚集
是根据文档字段所包含的值运算某些统计特征值,比如:平均值,总和等。 - 桶型聚集
根据一定的分组标准将文档归到不同的组中,这些分组在 Elasticsearch 中被称为桶( Bucken),桶型聚集与 SQL 中 group by 的作用类似,一 般会与指标聚集嵌套使用 - 管道聚集
可以理解为聚集结果的再聚集,它一般以另 一个聚集结果作为输人,然后在此基础上再做聚集 - 矩阵聚集
不细说
11.1、指标聚集
11.1.1、平均聚集:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
#聚集名称,是用 户自定义的,
"delay_avg": {
#聚集类型,es内置的
"avg": {
#聚集体,聚集体中可以再包含子聚集
"field": "FlightDelayMin"
}
}
}
}
上面计算了:航班的平均延误时间。请求参数 fiter _path 将返回结果的其他字段过滤掉了,否则查询的结果中将包含 kibana_sample_data_flights 索引中的文档。
查询结果如下:
aggregations 是关键字,代表这是聚集查询的结果。其中的 delay_avg 则是在聚集查询中定义的聚集名称,value 是聚集运算的结果。
{
"aggregations" : {
"delay_avg" : {
"value" : 47.33517114633586
}
}
}
计算了飞往中国的航班平均延误时间: 如下:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query":{
"match": {
"DestCountry": "CN"
}
},
"aggs": {
"delay_avg": {
"avg": {"field": "FlightDelayMin"}
}
}
}
11.1.2、计数聚集
计数聚集用于统计字段值的数量,
而极值聚集则是查找字段的极大值和极小 值。
- value_count 聚集:用于统计从 字段中取值的总数
- cardinality 聚集:用于统计不重复数值的总数,如同sql中的distinct
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"country_code": {
#cardinality 聚集统计了 DestCountry 字段非重复值的数量,类似 于 SQL 中的 distinct。
"cardinality": {"field": "DestCountry"}
},
"total_country": {
#value_count 聚集则统计了 DestCountry 字段所有返回值的 数量,类似于 SQL 中的 count。
"value_count": {"field": "DestCountry"}
}
}
}
11.1.3、极值聚集
极值聚集是在文档中提取某一字段最大值或最小值的聚集,包括 max 聚集 和 min 聚集。
聚集有 max_price 和 min_price 两个,它们分别计算了机票价格的 最大的最小值,如下:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"max_price": {
"max": {"field": "AvgTicketPrice"}
},
"min_price":{
"min": {"field": "AvgTicketPrice"}
}
}
}
11.1.4、统计聚集
统计聚集包含 stats 聚集和 extended_stats 聚集两种,
stats : 返回的统计数据是一些比较基本的数值,
extended_status:包含一些比较专业的统计数值。
stats 聚集
中对机票价格做统计:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"prices_status": {
"stats": {"field": "AvgTicketPrice"}
}
}
}
查询结果如下:
{
"aggregations" : {
"prices_status" : {
"count" : 13059,
"min" : 100.0205307006836,
"max" : 1199.72900390625,
"avg" : 628.2536888148849,
"sum" : 8204364.922233582
}
}
}
extended_stats 聚集
extended_stats 聚集增加了几项统计数据,这包括平方和、方差、标准方差 和标准方差偏移量。从使用的角度来看,extended_stats 聚集与 stats 聚集完全 相同,只是聚集类型不同。
11.1.5、百分位聚集
百分位聚集根据文档字段值统计字段值按百分比的分布情况,包括 pecrentiles 聚集和 percentile_ranks 两种。
前者统计的是百分比与值的对应关系, 而后者正好相反统计值与百分比的对应关系。
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"price_percentile": {
#设置字段百分比
"percentiles": {"field":"AvgTicketPrice", "percents": [25,50,75,100]}
},
"price_percentile_rank": {
# 设置组值,然后根据这些值分别计算落在不同值区间的百分比。
"percentile_ranks": {"field": "AvgTicketPrice", "values": [600,1200]}
}
}
}
执行结果:
{
"aggregations" : {
"price_percentile_rank" : {
"values" : {
"600.0" : 45.396263821423084,
"1200.0" : 100.0
}
},
"price_percentile" : {
"values" : {
#25%的机票价格都小于 410. 0127977258341
"25.0" : 410.0089175627301,
"50.0" : 640.362667150751,
"75.0" : 842.2593898341107,
"100.0" : 1199.72900390625
}
}
}
}
11.2、使用范围分桶
桶型聚集与 SQL 语句中的 group by 子句极为相似。
由于单纯使用桶型聚集只返回桶内文档数量,意义并不大,所以多数情况下 都是将桶型聚集与指标聚集以父子关系的形式组合在起使用。桶型聚集作为父聚 集起到分组的作用。而指标聚集则以子聚集的形式出现在桶型聚集中, 起到分 组统计的作用。比如将用户按性别分组,然后统计他们的平均年龄。
11.2.1、数值范围
range、date_range 与 ip_range 这三种类型的聚集都用于根据字段的值范围 内对文档分桶,字段值在同一范围内的文档归入同一桶中。每个值范围都可通过 from 和 to 参数指定,范围包含 from 值但不包含 to 值,用数学方法表示就是[from, to)。 在设置范围时,可以设置一个也可以设置多个,范围之间并非一定要连续, 可以有间隔也可以有重叠。
range 聚集
不定from的,从0开始
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"price_ranges":{
"range":{
"field": "AvgTicketPrice" ,
"ranges":[
{"to": 300 },
{"from": 300,"to": 600 },
{"from": 600,"to": 900 },
{"to": 900 }
]
}
}
}
}
date_range 聚集
按日期范围分桶
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"mar_flights":{
"date_range":{
"field": "timestamp" ,
"ranges":[
{"from": "2019-03-01","to": "2019-03-30" }
],
"format": "yyyy-MM-dd"
}
}
}
}
ip_range 聚集
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"local":{
"ip_range":{
"field": "clientip" ,
"ranges":[
{"from": "157.4.77.0", "to": "157.4.77.255"},
{"from": "105.32.127.0", "to": "105.32.127.255"}
]
}
}
}
}
11.2.2、间隔范围
histogram 聚集
histogram 聚集以数值为间隔定义数值范围,字段值具有相同范围的文档将 落入同桶中
以 100 为间隔做分桶,可以通过返回结果的 doc_count 字 段获取票价在每个区间的文档数量
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"price_histo": {
"histogram": {
"field": "AvgTicketPrice",
#间隔范围为100
"interval": 100,
//定义起始点,起算点进行偏移,从50开始
"offset":50 ,
"keyed": false
}
}
}
}
结果:
结果间隔100,然后如果需要以count升序排序如下:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"price_histo": {
"histogram": {
"field": "AvgTicketPrice",
"interval": 100,
"offset":50 ,
"keyed": false,
# 添加以count升序
"order": {
"_count": "asc"
}
}
}
}
}
date_histogram 聚集
date_histogra 聚集以时间为间隔定义日期范围,字段值具有相同日期范围的 文档将落入同一桶中。同样,返回结果中也会包含每个间隔范围内的文档数量 doc_count。
统计每月航班数量:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs": {
"month flights": {
"date_histogram": {"field": "timestamp", "interval": "month"}
}
}
}
interval这个参数将要过期,替代的是 fixed_interval 和 calendar_interval。
桶的数量:由间隔范围
auto_date_histogram 聚集
预先指定需要返回多少个桶,那么间隔值 也可以通过桶的数量以及字段值跨度共同确定
定义需要返回 10 个时间段的桶:如下:
POST /kibana_sample_data_flights/_search?size=0
{
"aggs":{
"age_group" : {
"auto_date_histogram" : { "field": "timestamp", "buckets" :10 }
}
}
}
11.2.3、子聚集(聚集嵌套)
把分桶后的文档 再作计算,比如avg group by 。
先按月对从中国起飞的航班做了分桶,然后又通过聚集嵌套计算每月平均 延误时间:
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
# 先筛选出CN的航班
"query": {
"term": {"OriginCountry": "CN"}
},
"aggs": {
#先按月分桶
"date_price_histogram": {
"date_histogram": {
"field": "timestamp", "interval": "month"
},
# 嵌套聚集,然后又计算按延误时间平均值
"aggs": {
"avg_price": {
"avg": { "field": "FlightDelayMin" }
}
}
}
}
}
对字符串类型进行分桶---- 使用词项分桶
12、使用词项分桶
对字符器分桶有:terms、significant_terms 和 significant_text 聚集。
字符器类型,特别是text类型在进入索引时,要分词,这种词项的分桶比较慢,为了加快速度,又引入了样本分桶,提高词分桶的性能。
12.1、terms聚集
terms 聚集根据文档字段中的词项做分桶,所有包含同一词项的文档将被归 人同一桶中,聚集结果中包含字段中的词项及其词频,在默认情况下还会根据词 频排序,所以 terms 聚集也可用于热词展示,由于 terms 聚集在统计词项的词频数据时需要打开它的 fielddata 机制。fielddata 机制对内存消耗较大且有导致内存 溢出的可能, 所以 terms 聚集一般针对 keyword 非 text 类型。
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"aggs":{
"country_terms": {
"terms":{ "field": "DestCountry", "size": 10 }
},
"country_terms_count":{
#对DestCountry字段,去重 统计和
"cardinality": {
"field": "DestCountry"
}
}
}
}
terms 聚集的 field 参数定义了提取词项的字段为 DestCountry, 它的词项在 返回结果中会按词频由高到低依次展示,词频会在返回结果的 doc_count 字段中 展示。另一个参数 size 则指定了只返回 10 个词项,这相当把 DestCountry 字段 中词频前 10 名检索出来。
12.2、significant_terms 聚集
terms 聚集统计在字段中的词项及其词频,聚集结果会按各词项总的词频排 序,并讲现次数最多的词项排在最前面,这非常适合做推荐及热词类的应用。
但 按词频总数来统计不一定可能是总是正确的选择,在一些检索条件已知的情况下,一些 词频总数比较低的词项反而 在检索条件已知的情况下 词频变高,那这些词反而更合适推荐热词。
比如: 在10000 篇文章中,我们搜索es, 得到200篇文章,占比为2%。
但我们加一个条件:在标题中含有nosql的 文章 再去搜索es,此时搜索出的文章为 180篇, 占子集比为:18%。占比显著升高,说明在文章标题有nosql的条件下 ,es变得更为重要。
于是significant_terms 聚集 将文档和词项分为 前景集和背景集。前景集对应 条件下的子集,背景集:对应 所有文档集合。
用query 指定条件,条件下的集合 对应 前景集,运算field参数 : 指定搜索词项。
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
# query条件,指定 条件下的子集为 前景集
"query": {
"term":{
"OriginCountry": {"value": "IE"}
}
},
//对DestCountry字段为 搜索词项
"aggs": {
"dest":{
"significant_terms": { "field": "DestCountry" }
}
}
}
,query 参数使用 DSL 指定了前景集为出发国家为 IE (即爱尔兰)的 航班,而聚集查询中则使用 significant_ terms 统计到达国家的前景集词频和背景 集词频。来看下返回结果:
{
"aggregations" : {
"dest" : {
"doc_count" : 119,
"bg_count" : 13059,
"buckets" : [
{
"key" : "GB",
#在前景集中,词项出现在的次数,也就是说在出发地是 IE的集合中,到达国家为GB,出现的次数为12次
"doc_count" : 12,
"score" : 0.19491470110905626,
# 在背景集中,搜索词项出现的次数,在所有航班中,达到地是GB出现的次数为 449次
"bg_count" : 449
},
{
#出发地是IE的集合中,到达国家为KR ,出现的次数为7次
"key" : "KR",
"doc_count" : 7,
"score" : 0.15232998092035055,
#到达地为KR,在所有航班中出现的次数为214次
"bg_count" : 214
},
{
"key" : "PE",
"doc_count" : 4,
"score" : 0.15082268201398205,
"bg_count" : 80
},
{
"key" : "CO",
"doc_count" : 4,
"score" : 0.12852820507647145,
"bg_count" : 91
},
{
"key" : "IN",
"doc_count" : 8,
"score" : 0.0910024946739459,
"bg_count" : 373
},
{
"key" : "EC",
"doc_count" : 6,
"score" : 0.08965790336983642,
"bg_count" : 237
},
{
"key" : "PR",
"doc_count" : 3,
"score" : 0.04633841366161068,
"bg_count" : 116
},
{
"key" : "JP",
"doc_count" : 10,
"score" : 0.035111171691658886,
"bg_count" : 774
},
{
"key" : "US",
"doc_count" : 21,
"score" : 0.028200604970369705,
"bg_count" : 1987
},
{
"key" : "NO",
"doc_count" : 3,
"score" : 0.02141702682394835,
"bg_count" : 178
}
]
}
}
}
12.3、significant_text 聚集
term最好用在keyworkd,如果要查询text类型,那么要开启 Fielddata,如果不想开启Fielddata,又要果询text类型,那么就要用significant_text 。
significant_text和significant_terms一样, 只是terms用在keyworkd类型上, text用在text类型上。
但text的效率还是慢,为了提高速度,又提供了样本聚集。
12.4、样本聚集
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"term":{
"OriginCountry": {"value": "IE"}
}
},
"aggs": {
#抽样,然后在抽样的数据 再去聚集
"sample_data":{
"sampler": {
"shard_size": 100
},
"aggs": {
"dest":{
"significant_terms": { "field": "DestCountry" }
}
}
}
}
}
抽样中,又提供了 剔除相同的样本
POST /kibana_sample_data_flights/_search?filter_path=aggregations
{
"query": {
"term":{
"OriginCountry": {"value": "IE"}
}
},
"aggs": {
#去重抽样
"sample_data":{
# 去重抽样
"diversified_sampler": {
"shard_size": 100,
//对AvgTicketPrice字段去重 抽样
"field": "AvgTicketPrice"
},
"aggs": {
"dest":{
"significant_terms": { "field": "DestCountry" }
}
}
}
}
}
13、单桶聚集
查看另一篇:https://blog.csdn.net/lh87270202/article/details/107774919