ElasticSearch教程入门到精通——第一部分(基于ELK技术栈elasticsearch 8.x新特性)

ElasticSearch教程入门到精通------第一部分(基于ELK技术栈elasticsearch 8.x新特性)

  • [1. ElasticSearch安装(略)](#1. ElasticSearch安装(略))
  • [2. ElasticSearch基础功能](#2. ElasticSearch基础功能)
    • [2.1 索引操作](#2.1 索引操作)
      • [2.1.1 创建索引](#2.1.1 创建索引)
      • [2.1.2 Head 索引](#2.1.2 Head 索引)
      • [2.1.3 查询索引](#2.1.3 查询索引)
        • [2.1.3.1 查询单独索引](#2.1.3.1 查询单独索引)
        • [2.1.3.2 查询全部索引](#2.1.3.2 查询全部索引)
      • [2.1.4 增加配置](#2.1.4 增加配置)
      • [2.1.5 删除索引](#2.1.5 删除索引)
    • [2.2 文档操作](#2.2 文档操作)
      • [2.2.1 创建文档](#2.2.1 创建文档)
      • [2.2.2 查询文档](#2.2.2 查询文档)
        • [2.2.2.1 查询个别文档](#2.2.2.1 查询个别文档)
        • [2.2.2.2 查询文档所有数据](#2.2.2.2 查询文档所有数据)
      • [2.2.3 修改数据](#2.2.3 修改数据)
      • [2.2.4 删除数据](#2.2.4 删除数据)
    • [2.3 文档搜索](#2.3 文档搜索)
      • [2.3.1 Match分词查询](#2.3.1 Match分词查询)
      • [2.3.2 使用term精确匹配某个字段的关键词](#2.3.2 使用term精确匹配某个字段的关键词)
      • [2.3.3 查询结果中过滤某些不需要的字段](#2.3.3 查询结果中过滤某些不需要的字段)
      • [2.3.4 多条件组合查询](#2.3.4 多条件组合查询)
        • [2.3.4.1 查询name中含有zhang或age为40的数据](#2.3.4.1 查询name中含有zhang或age为40的数据)
        • [2.3.4.2 查询文档中name中必须含有zhang或者age必须大于等于30岁的数据](#2.3.4.2 查询文档中name中必须含有zhang或者age必须大于等于30岁的数据)
        • [2.3.4.3 查询结果排序](#2.3.4.3 查询结果排序)
      • [2.3.5 分页查询](#2.3.5 分页查询)
    • [2.4 聚合搜索](#2.4 聚合搜索)
      • [2.4.1 根据age将查询结果进行分组聚合](#2.4.1 根据age将查询结果进行分组聚合)
      • [2.4.2 查询年龄大于等于40岁的,并将结果按照age分组聚合](#2.4.2 查询年龄大于等于40岁的,并将结果按照age分组聚合)
      • [2.4.3 根据age分组聚合,再对聚合后的结果按照age求平均值](#2.4.3 根据age分组聚合,再对聚合后的结果按照age求平均值)
      • [2.4.4 获取结果集中的前N个数据](#2.4.4 获取结果集中的前N个数据)
      • [2.4.5 获取结果集中按照age字段排序后求取前N个数据](#2.4.5 获取结果集中按照age字段排序后求取前N个数据)
    • [2.5 索引模板](#2.5 索引模板)
      • [2.5.1 创建/修改 索引](#2.5.1 创建/修改 索引)
      • [2.5.2 查看模板](#2.5.2 查看模板)
      • [2.5.3 更新模板](#2.5.3 更新模板)
      • [2.5.4 应用模板](#2.5.4 应用模板)
      • [2.5.5 删除模板](#2.5.5 删除模板)
    • [2.6 中文分词](#2.6 中文分词)
      • [2.6.1 分词操作](#2.6.1 分词操作)
      • [2.6.2 分词操作(不带插件情况下,中文拆分逻辑太适合)](#2.6.2 分词操作(不带插件情况下,中文拆分逻辑太适合))
      • [2.6.3 集成了IK插件后提供的分词](#2.6.3 集成了IK插件后提供的分词)
        • [2.6.3.1 ik_smart------最少切分](#2.6.3.1 ik_smart——最少切分)
        • [2.6.3.2 ik_max_word------最细粒度切分](#2.6.3.2 ik_max_word——最细粒度切分)
      • [2.6.4 自定义分词效果](#2.6.4 自定义分词效果)
    • [2.7 文档评分机制(转载)](#2.7 文档评分机制(转载))
      • [2.7.1 TF-IDF 原理](#2.7.1 TF-IDF 原理)
        • [2.7.1.1 计算公式](#2.7.1.1 计算公式)
        • [2.7.1.2 示例说明](#2.7.1.2 示例说明)
        • [2.7.1.3 计算TF](#2.7.1.3 计算TF)
        • [2.7.1.4 计算IDF](#2.7.1.4 计算IDF)
        • [2.7.1.5 TF-IDF计算](#2.7.1.5 TF-IDF计算)
      • [2.7.2 Elasticsearch打分机制](#2.7.2 Elasticsearch打分机制)
        • [2.7.2.1 示例说明](#2.7.2.1 示例说明)
        • [2.7.2.2 计算 TF 值](#2.7.2.2 计算 TF 值)
        • [2.7.2.3 计算 IDF 值](#2.7.2.3 计算 IDF 值)
        • [2.7.2.4 计算文档得分](#2.7.2.4 计算文档得分)
        • [2.7.2.5 增加新的文档测试得分](#2.7.2.5 增加新的文档测试得分)
      • [2.7.3 案列](#2.7.3 案列)
        • [2.7.3.1 需求](#2.7.3.1 需求)
        • [2.7.3.2 准备数据](#2.7.3.2 准备数据)
        • [2.7.3.3 查询数据](#2.7.3.3 查询数据)

1. ElasticSearch安装(略)

2. ElasticSearch基础功能

2.1 索引操作

2.1.1 创建索引

ES软件的索引可以类比为MySQL中表的概念,创建一个索引,类似于创建一个表。查询完成后,Kibana右侧会返回响应结果及请求状态

powershell 复制代码
PUT test_index

重复创建索引------报错!

2.1.2 Head 索引

powershell 复制代码
head test_index
powershell 复制代码
head test_index1

2.1.3 查询索引

2.1.3.1 查询单独索引
powershell 复制代码
GET test_index
2.1.3.2 查询全部索引
cpp 复制代码
GET _cat/indices

2.1.4 增加配置

JSON格式的主题内容

json 复制代码
PUT test_index_1
{
	"aliases":{
		"test1":{}
	}
}

查询看结果

这样 别名就设置上了

powershell 复制代码
GET test1

试一试~

注意:ES软件不支持修改索引信息,如果想要修改,只能新建

2.1.5 删除索引

powershell 复制代码
DELETE test_index_1

再删除一次 ~!


2.2 文档操作

文档是ES软件搜索数据的最小单位,不依赖预先定义的模式,所以可以将文档类比为表的一行JSON类型的数据。我们知道关系型数据库中,要提前定义字段才能使用,在Elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。

2.2.1 创建文档

索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为JSON格式

powershell 复制代码
PUT test_doc

添加索引

powershell 复制代码
PUT test_doc/_doc
{
	"id":1001,
	"name":"zhangsan",
	"age":30
}

为什么只让用Post 不让用PUT?

  • 因为PUT创建的时候,创建数据具有唯一性标识
powershell 复制代码
PUT test_doc/_doc/1001
{
	"id":1001,
	"name":"zhangsan",
	"age":30
}
powershell 复制代码
POST test_doc/_doc
{
	"id":1002,
	"name":"lisi",
	"age":40
}

2.2.2 查询文档

2.2.2.1 查询个别文档
powershell 复制代码
GET test_doc/_doc/1001
powershell 复制代码
GET test_doc/_doc
2.2.2.2 查询文档所有数据
powershell 复制代码
GET test_doc/_search

2.2.3 修改数据

powershell 复制代码
PUT test_doc/_doc/1001
{
	"id":10011,
	"name":"zhangsan1",
	"age":300,
	"tel":123123
}

POST 也可以

2.2.4 删除数据

powershell 复制代码
DELETE test_doc/_doc/1002

再删一次

2.3 文档搜索

powershell 复制代码
PUT test_query
powershell 复制代码
PUT test_query/_bulk
{"index": {"_index": "test_query","_id": "1001"}}
{"id": "1001","name":"zhang san","age":30}
{"index": {"_index": "test_query","_id": "1002"}}
{"id": "1002","name":"li si","age": 40}
{"index": {"_index": "test_query","_id": "1003"}}
{"id": "1003", "name": "wang wu","age" : 50}
{"index": {"_index": "test_query","_id": "1004"}}
{"id": "1004","name": "zhangsan", "age" : 30}
{"index": {"_index": "test_query","_id": "1005"}}
{"id": "1005","name": "lisi","age":40}
{"index": {"_index": "test_query","_id": "1006"}}
{"id": "1006", "name ": "wangwu","age" : 50}

2.3.1 Match分词查询

Match 是分词查询,ES会将数据分词保存

powershell 复制代码
GET test_query/_search
{
	"query":{
		"match":{
			"name":"zhangsan"
		}
	}
}
powershell 复制代码
GET test_query/_search
{
	"query":{
		"match":{
			"name":"zhang"
		}
	}
}
powershell 复制代码
GET test_query/_search
{
	"query":{
		"match":{
			"name":"zhang li"
		}
	}
}

2.3.2 使用term精确匹配某个字段的关键词

但是我不想分词~

powershell 复制代码
GET test_query/_search
{
	"query":{
		"term":{
			"name":{
				"value":"zhang san"
			}
		}
	}
}
powershell 复制代码
GET test_query/_search
{
	"query":{
		"term":{
			"name":{
				"value":"zhangsan"
			}
		}
	}
}

2.3.3 查询结果中过滤某些不需要的字段

某些情况下,不需要查询结果中返回所有的字段,就可以通过添加"_source"进行限制

powershell 复制代码
GET test_query/_search
{
  "_source": ["name","age"], 
  
  "query": {
    "match": {
      "name": "zhang"
    }
  }
}

2.3.4 多条件组合查询

组合查询的关键语法是需要在查询条件中使用bool关键字

2.3.4.1 查询name中含有zhang或age为40的数据

这个需求类似于mysql 中的or的语法,在es中使用should可以满足类似的需求

powershell 复制代码
GET test_query/_search
{
  "query": {
    "bool": {
      "should": [
        [
          {
            "match":{
              "name":"zhang"
            }
          },
          {
            "match":{
              "age":40
            }
          }
        ]
      ]
    }
  }
}
2.3.4.2 查询文档中name中必须含有zhang或者age必须大于等于30岁的数据

组合使用should和must

powershell 复制代码
GET test_query/_search
{
  "query": {
    "bool": {
      "must": [
        [
          {
            "match":{
              "name":"zhang"
            }
          }
        ]
      ],
      
      "should": [
        {
          "range": {
            "age": {
              "gte": 30
            }
          }
        }
      ]
    }
  }
}
2.3.4.3 查询结果排序

查询name中含有 zhang的文档,并按照age排序

powershell 复制代码
GET test_query/_search
{
  
  "query": {
    "match": {
      "name": "zhang"
    }
  },
  "sort":[
    {
      "age" : {
        "order":"desc"
      }
    }
  ]
}

2.3.5 分页查询

语法

powershell 复制代码
GET 索引名称/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,        //从第几条开始查询
  "size": 2         //每次查询多少数据
}

看下面的查询结果

计算公式:

f r o m = ( p a g e n o − 1 ) ∗ s i z e from = (pageno -1)*size from=(pageno−1)∗size

2.4 聚合搜索

实际业务中,经常会涉及到对查询的结果根据某个或者某些字段进行聚合,类似于mysql中的group by语法;

2.4.1 根据age将查询结果进行分组聚合

注意点:这里 "size"设置为0表示查询结果中不展示其他非聚合结果的信息

powershell 复制代码
GET test_query/_search
{
 
  "aggs": {
    "aggAge": {
      "terms": {
        "field": "age"
      }
    }
  },
 
  "size": 0
}

2.4.2 查询年龄大于等于40岁的,并将结果按照age分组聚合

powershell 复制代码
GET test_query/_search
{
 
 "query": {
   "range": {
     "age": {
       "gte": 40
     }
   }
 }, 
 
  "aggs": {
    "aggAge": {
      "terms": {
        "field": "age"
      }
    }
  },
 
  "size": 0
}

查询结果如下

2.4.3 根据age分组聚合,再对聚合后的结果按照age求平均值

powershell 复制代码
GET test_query/_search
{
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age"
      },
      
      "aggs": {
        "avgAgg": {
          "avg": {
            "field": "age"
          }
        }
      }
      
    }
  },
  "size": 0
}

查询结果如下

2.4.4 获取结果集中的前N个数据

powershell 复制代码
GET test_query/_search
{
  "aggs": {
    "top3": {
      "top_hits": {
        "size": 3
      }
    }
  },
  "size": 0
}

查询结果如下

2.4.5 获取结果集中按照age字段排序后求取前N个数据

powershell 复制代码
GET test_query/_search
{
  "aggs": {
    "top3": {
      "top_hits": {
        "sort": [
          {
          "age" : {
              "order":"desc"
            }
          }
        ], 
        "size": 3
      }
    }
  },
  "size": 0
}

2.5 索引模板

我们之前对索引进行一些配置信息设置,但是都是在单个索引上进行设置。在实际开发中,我们可能需要创建不止一个索引,但是每个索引或多或少都有一些共性。

比如我们在设计关系型数据库时,一般都会为每个表结构设计一些常用的字段,比如:创建时间更新时间备注信息 等。elasticsearch 在创建索引的时候,就引入了模板的概念,你可以先设置一些通用的模板,在创建索引的时候,elasticsearch会先根据你创建的模板对索引进行设置。

elasticsearch中提供了很多的默认设置模板,这就是为什么我们在新建文档的时候,可以为你自动设置一些信息, 做一些字段转换等。

2.5.1 创建/修改 索引

索引可使用预定义的模板进行创建这个模板称作Indextemplates.模板设置包括settingsmappings

powershell 复制代码
PUT _template/mytemplate

{
  "index_patterns": [
    "my*"  // 该模板自动适用于索引名称以 my 开头的索引
  ],
  // 设置模板规则
  "settings": {
    "index": {
      "number_of_shards": "2" // 分片数量
    }
  },
  // 影射规则
  "mappings": {
    "properties": {
      // 字段 now 的类型及格式
      "now": {
        "type": "date",
        "format": "yyyy/MM/dd"
      }
    }
  }
}

可以多长操作!!

2.5.2 查看模板

powershell 复制代码
GET _template/模板名称

2.5.3 更新模板

与创建命令相同,只要创建的模板名称已存在,就是更新操作,新规则覆盖旧规则

如果创建的是索引,不是索引模板,当要创建的索引已存在时,操作是不会成功的,会出错,提示索引已存在

2.5.4 应用模板

只要新创建的 索引 符合 索引模板 的匹配规则,就会自动应用模板

如:新创建 my_index_template 索引,以 my 开头,符合匹配规则

powershell 复制代码
// 应用索引模板;创建以 my 开头的索引
PUT my_index_template
// 查询创建的索引
GET my_index_template


2.5.5 删除模板

powershell 复制代码
DELETE _template/索引模板名称

删除后查询;结果为空;查询不存在的索引模板时,结果都为空

2.6 中文分词

我们在使用Elasticsearch官方默认的分词插件时会发现,其对中文的分词效果不佳,经常分词后得效果不是我们想要得。

2.6.1 分词操作

powershell 复制代码
GET _analyze
{
  "analyzer": "standard", 
  "text": ["zhang san"]
}

2.6.2 分词操作(不带插件情况下,中文拆分逻辑太适合)

powershell 复制代码
GET _analyze
{
  "analyzer": "chinese", 
  "text": ["我是一个三好学生"]
}

2.6.3 集成了IK插件后提供的分词

一定注意!版本下载的正确性!!!

别忘了重新启动!!

2.6.3.1 ik_smart------最少切分
powershell 复制代码
GET _analyze
{
  "analyzer": "ik_smart", 
  "text": ["我是一个三好学生"]
}
2.6.3.2 ik_max_word------最细粒度切分

相较于上者,分得更加精细

powershell 复制代码
GET _analyze
{
  "analyzer": "ik_max_word", 
  "text": ["我是一个三好学生"]
}

2.6.4 自定义分词效果


重新启动ES!!!

2.7 文档评分机制(转载)

powershell 复制代码
PUT test_score

PUT test_score/_doc/1001
{
  "text": "zhang kai shou bi, yin jie tai yang"
}

PUT test_score/_doc/1002
{
  "text": "zhang san"
}

GET test_score/_search?explain=true
{
  "query": {
    "match": {
      "text": "zhang"
    }
  }
}

Elasticsearch 的得分机制是一个基于词频和逆文档词频的公式,简称为 TF-IDF 公式,所以先来研究下 TF-IDF原理。

2.7.1 TF-IDF 原理

  • 英文全称:Term Frequency - Inverse Document Frequency
  • 中文名称:词频-逆文档频率

常用于文本挖掘,资讯检索等应用,在NLP以及推荐等领域都是一个常用的指标,用于衡量字词的重要性。

比较直观的解释是,如果一个词本来出现的频率就很高,如the,那么它就几乎无法带给读者一些明确的信息。

一般地,以TF-IDF衡量字词重要性时

  • 某个字词在某个文档中出现的频率越高,那么该字词对该文档就有越大的重要性,它可能会是文章的关键词(词在单个文档中出现的频率,相对于当个文档!!!)
  • 但若字词在词库中出现的频率越高,那么字词的重要性越低,如the。(相对于整个文档集合,也就是词库)
2.7.1.1 计算公式

TF-IDF即是两者相乘,词频乘以逆文档频率,如下:

TF-IDF = T F ∗ I D F =TF*IDF =TF∗IDF

下标ij的含义:编号为j的文档中的词语i在该文档中的词频,即所占比例,n为该词语的数量。如下:

换言之,就是词语出现的次数与文档中所有词总数的比值。

T F i j = n i j n ∗ j TF_{ij} = \frac{n_{ij}}{n_{*j}} TFij=n∗jnij

N表示文档总数,Ni表示文档集中包含了词语 i i i 的文档数。

对分子分母加一是为了避免某些词语没有在文档中出现过,导致分母为零的情况。

IDF针对某个词计算了它的逆文档频率,即包含该词语的文档比例的倒数(再取对数),若IDF值越小,分母越大,说明这个词语在文档集中比较常见不具有鲜明的信息代表性,TF-IDF的值就小。

总之TF-IDF的值,通常希望它越大越好,大值代表性强。如下:

I D F i = l o g ( N + 1 N i + 1 ) IDF_i=log (\frac{N+1}{N_i+1}) IDFi=log(Ni+1N+1)

2.7.1.2 示例说明

有两个文档,即doc1doc2,并去它们的并集

py 复制代码
doc1 = "The cat sat on my bed"
doc2 = "The dog sat on my knees"
# 构建词库,union是并集操作
wordSet = set(doc1.split()).union(set(doc2.split()))

两个文档的并集如下:

{'The','bed','cat','dog','knees','my','on','sat'}

doc1doc2两个文档对应的词在并集中的统计情况:

序号 cat sat my on dog bed The knees
0 1 1 1 1 0 1 1 0
1 0 1 1 1 1 0 1 1
2.7.1.3 计算TF

计算词频 TF,对单个文档统计:

再理解一下,何为TF,表示单个单词占当前文档所有单词集合的比值。即1/6=0.16666666666...

cat sat my on dog bed The knees
1 1 1 1 0 1 1 0
0.166666... 0.166666... 0.166666... 0.166666... 0 0.166666... 0.166666... 0
2.7.1.4 计算IDF

逆文档频率IDF,全局只有一份逆文档频率,对所有文档统计

N表示文档总数,Ni`表示文档集中包含了词语i的文档数。

此时N=2,共有两个文档。Ni表示含有单词的文档个数。

cat sat my on dog bed The knees
0.17609125... 0.0 0.0 0.0... 0.17609125... 0.17609125... 0.0 0.17609125...
2.7.1.5 TF-IDF计算

最终计算:TF-IDF = TF * IDF

序号 cat sat my on dog bed The knees
0 0.029349 0 0 0 0.029349 0 0 0
1 0 0 0 0.029349 0 0 0 0.029349

2.7.2 Elasticsearch打分机制

上面介绍了TF-IDF的原理,而ES的得分机制就是基于词频和逆文档词频的公式,即TF-IDF公式。
s c o r e ( q , d ) = c o o r d ( q , d ) ⋅ q u e r y N o r m ( q ) ⋅ ∑ t i n q ( t f ( t i n d ) ⋅ i d f ( t ) 2 ⋅ t . g e t B o o s t ( ) ⋅ n o r m ( t , d ) ) score(q,d) = coord(q,d)\cdot queryNorm(q)\cdot \sum_{t in q}(tf(t in d)\cdot idf(t){^2}\cdot t.getBoost()\cdot norm(t,d)) score(q,d)=coord(q,d)⋅queryNorm(q)⋅tinq∑(tf(tind)⋅idf(t)2⋅t.getBoost()⋅norm(t,d))

公式中将查询作为输入,使用不同的手段来确定每一篇文档的得分,将每一个因素最后通过公式综合起来,返回该文档的最终得分。这个综合考量的过程,在ES中这种相关性称为得分。

考虑到查询内容和文档的关系比较复杂,所以公式中需要输入的参数和条件非常得多,但是其中比较重要的其实是TF-IDF算法 ,再次解释一下。

  • TF (词频)

Term Frequency : 搜索文本中的各个词条在查询文本中出现了多少次,次数越多,就越相关,得分会比较高

  • IDF(逆文档频率)

Inverse Document Frequency : 搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,说明越不重要,也就越不相关,得分就比较低。

2.7.2.1 示例说明

在查询语句的最后加上explain=true ,会把得分过程打印。

注:当前ElasticSearchscorpios索引里,只有一个文档。

powershell 复制代码
PUT itwluo

PUT itwluo/_doc/1001
{
  "text": "java"
}

GET itwluo/_search
{
  "query": {
    "match": {
      "text": "java"
    }
  }
}

result

json 复制代码
{
  "took": 992,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.2876821,
    "hits": [
      {
        "_index": "itwluo",
        "_id": "1001",
        "_score": 0.2876821,
        "_source": {
          "text": "java"
        }
      }
    ]
  }
}

详细结果

json 复制代码
{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.2876821,
    "hits": [
      {
        "_shard": "[itwluo][0]",
        "_node": "EX7ZCQpSRLu-OWEZjQazog",
        "_index": "itwluo",
        "_id": "1001",
        "_score": 0.2876821,
        "_source": {
          "text": "java"
        },
        "_explanation": {
          "value": 0.2876821,
          "description": "weight(text:java in 0) [PerFieldSimilarity], result of:",
          "details": [
            {
              "value": 0.2876821,
              "description": "score(freq=1.0), computed as boost * idf * tf from:",
              "details": [
                {
                  "value": 2.2,
                  "description": "boost",
                  "details": []
                },
                {
                  "value": 0.2876821,
                  "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                  "details": [
                    {
                      "value": 1,
                      "description": "n, number of documents containing term",
                      "details": []
                    },
                    {
                      "value": 1,
                      "description": "N, total number of documents with field",
                      "details": []
                    }
                  ]
                },
                {
                  "value": 0.45454544,
                  "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                  "details": [
                    {
                      "value": 1,
                      "description": "freq, occurrences of term within document",
                      "details": []
                    },
                    {
                      "value": 1.2,
                      "description": "k1, term saturation parameter",
                      "details": []
                    },
                    {
                      "value": 0.75,
                      "description": "b, length normalization parameter",
                      "details": []
                    },
                    {
                      "value": 1,
                      "description": "dl, length of field",
                      "details": []
                    },
                    {
                      "value": 1,
                      "description": "avgdl, average length of field",
                      "details": []
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

新增数据后,观察分值变化

powershell 复制代码
PUT itwluo/_doc/1002
{
  "text": "java bigdata"
}

#查询文档数据
GET itwluo/_search?explain=true
{
  "query": {
    "match": {
      "text": "java"
    }
  }
}

详细结果

json 复制代码
{
  "took": 609,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.21110919,
    "hits": [
      {
        "_shard": "[itwluo][0]",
        "_node": "EX7ZCQpSRLu-OWEZjQazog",
        "_index": "itwluo",
        "_id": "1001",
        "_score": 0.21110919,
        "_source": {
          "text": "java"
        },
        "_explanation": {
          "value": 0.21110919,
          "description": "weight(text:java in 0) [PerFieldSimilarity], result of:",
          "details": [
            {
              "value": 0.21110919,
              "description": "score(freq=1.0), computed as boost * idf * tf from:",
              "details": [
                {
                  "value": 2.2,
                  "description": "boost",
                  "details": []
                },
                {
                  "value": 0.18232156,
                  "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                  "details": [
                    {
                      "value": 2,
                      "description": "n, number of documents containing term",
                      "details": []
                    },
                    {
                      "value": 2,
                      "description": "N, total number of documents with field",
                      "details": []
                    }
                  ]
                },
                {
                  "value": 0.5263158,
                  "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                  "details": [
                    {
                      "value": 1,
                      "description": "freq, occurrences of term within document",
                      "details": []
                    },
                    {
                      "value": 1.2,
                      "description": "k1, term saturation parameter",
                      "details": []
                    },
                    {
                      "value": 0.75,
                      "description": "b, length normalization parameter",
                      "details": []
                    },
                    {
                      "value": 1,
                      "description": "dl, length of field",
                      "details": []
                    },
                    {
                      "value": 1.5,
                      "description": "avgdl, average length of field",
                      "details": []
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      {
        "_shard": "[itwluo][0]",
        "_node": "EX7ZCQpSRLu-OWEZjQazog",
        "_index": "itwluo",
        "_id": "1002",
        "_score": 0.160443,
        "_source": {
          "text": "java bigdata"
        },
        "_explanation": {
          "value": 0.160443,
          "description": "weight(text:java in 0) [PerFieldSimilarity], result of:",
          "details": [
            {
              "value": 0.160443,
              "description": "score(freq=1.0), computed as boost * idf * tf from:",
              "details": [
                {
                  "value": 2.2,
                  "description": "boost",
                  "details": []
                },
                {
                  "value": 0.18232156,
                  "description": "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                  "details": [
                    {
                      "value": 2,
                      "description": "n, number of documents containing term",
                      "details": []
                    },
                    {
                      "value": 2,
                      "description": "N, total number of documents with field",
                      "details": []
                    }
                  ]
                },
                {
                  "value": 0.40000004,
                  "description": "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                  "details": [
                    {
                      "value": 1,
                      "description": "freq, occurrences of term within document",
                      "details": []
                    },
                    {
                      "value": 1.2,
                      "description": "k1, term saturation parameter",
                      "details": []
                    },
                    {
                      "value": 0.75,
                      "description": "b, length normalization parameter",
                      "details": []
                    },
                    {
                      "value": 2,
                      "description": "dl, length of field",
                      "details": []
                    },
                    {
                      "value": 1.5,
                      "description": "avgdl, average length of field",
                      "details": []
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    ]
  }
}
2.7.2.2 计算 TF 值

T F = f r e q / ( f r e q + k 1 ∗ ( 1 − b + b ∗ d l / a v g d l ) ) TF = freq/(freq + k1 * (1-b+b*dl/avgdl)) TF=freq/(freq+k1∗(1−b+b∗dl/avgdl))

参数 含义 取值
freq 文档中出现词条的次数 1.0
k1 术语饱和参数 1.2(默认值)
b 长度规格参数(单词长度对于整个文档的影响程度) 0.75(默认值)
dl 当前文中分解的字段长度 1.0
avgdl 查询文档中分解字段数量/查询文档数量 1.0
TF(词频) 1.0/(1+1.2 * (1-0.75+0.75 * 1.0/1.0)) 0.454545
2.7.2.3 计算 IDF 值

I D F = l n ( 1 + ( N − n + 0.5 ) / ( n + 0.5 ) ) IDF = ln(1+(N−n+0.5)/(n+0.5)) IDF=ln(1+(N−n+0.5)/(n+0.5))

参数 含义 取值
N 包含查询字段的文档总数(不一定包含查询词条) 1
n 包含查询词条的文档数 1
IDF(逆文档频率) log(1+(1-1+0.5)/(1+0.5)) 0.2875821

注:这里的 ln是底数为e 的对数

2.7.2.4 计算文档得分

s c o r e = t f b o o s t ∗ i d f ∗ t f score = tf boost∗idf∗tf score=tfboost∗idf∗tf

参数 含义 取值
boost 词条权重 2.2(基础值)*查询权重(1)
idf 逆文档频率 0.2876821
tf 词频 0.454545
score(得分) 2.20.28768210.454545 0.2876821
2.7.2.5 增加新的文档测试得分
  • 增加一个毫无关系的文档
yaml 复制代码
# 增加文档
PUT /scorpios/_doc/2
{
 "text" : "spark"
}
# 得分:0.6931741
GET /scorpios/_search
{
     "query": {
        "match": {
            "text": "hello"
        }
     } 
 }

因为新文档无词条相关信息,所以匹配的文档数据得分就应该较高

  • 增加一个一模一样的文档
yaml 复制代码
# 增加文档
PUT /scorpios/_doc/2
{
 "text" : "hello"
}

# 得分:0.18232156
GET /scorpios/_search
{
 	"query": {
 		"match": {
 			"text": "hello"
 		}
	}
}

因为新文档含词条相关信息,且多个文件含有词条,所以显得不是很重要,得分会变低

  • 增加一个含有词条,但是内容较多的文档
yaml 复制代码
# 增加文档
PUT /scorpios/_doc/2 
{
	"text" : "hello elasticsearch" 
}
# 得分:0.14874382
GET /scorpios/_search
{
     "query": {
         "match": {
         	"text": "hello"
         }
     }
 }

因为新文档含词条相关信息,但只是其中一部分,所以查询文档的分数会变得更低一些。

2.7.3 案列

2.7.3.1 需求

查询文档标题中含有Hadoop,Elasticsearch,Spark的内容,优先选择Spark的内容

2.7.3.2 准备数据
yaml 复制代码
# 创建索引
PUT /test
# 准备数据
PUT /test/_doc/1001
{
	"title" : "Hadoop is a Framework",
	"content" : "Hadoop 是一个大数据基础框架" 
}
PUT /test/_doc/1002
{
	"title" : "Hive is a SQL Tools",
	"content" : "Hive 是一个 SQL 工具" 
}
PUT /test/_doc/1003
{
	"title" : "Spark is a Framework",
	"content" : "Spark 是一个分布式计算引擎" 
}
2.7.3.3 查询数据
yaml 复制代码
# 查询文档标题中含有"Hadoop","Elasticsearch","Spark"的内容
GET /test/_search?explain=true
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "Hadoop", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Hive", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Spark", "boost": 1
            }
          }
        }
      ]
    }
  }
}

此时会发现,Spark的结果并不会放置在最前面

此时可以更改 Spark 查询的权重参数 boost,看看查询的结果有什么不同

yaml 复制代码
# 查询文档标题中含有"Hadoop","Elasticsearch","Spark"的内容
GET /test/_search?explain=true
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "Hadoop", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Hive", "boost": 1
            }
          }
        },
        {
          "match": {
            "title": {
              "query": "Spark", "boost": 2
            }
          }
        }
      ]
    }
  }
}
相关推荐
不会c+1 小时前
Elasticsearch入门
大数据·elasticsearch·搜索引擎
数据知道1 小时前
PostgreSQL 实战:一文掌握如何优雅的进行递归查询?
大数据·数据库·postgresql
重生之绝世牛码1 小时前
Linux软件安装 —— ClickHouse单节点安装(rpm安装、tar安装两种安装方式)
大数据·linux·运维·数据库·clickhouse·软件安装·clickhouse单节点
AIFQuant2 小时前
如何通过股票数据 API 计算 RSI、MACD 与移动平均线MA
大数据·后端·python·金融·restful
MasonYyp2 小时前
DSPy优化提示词
大数据·人工智能
happyboy19862112 小时前
2026 大专大数据技术专业零基础能考的证书有哪些?
大数据
大公产经晚间消息2 小时前
天九企服董事长戈峻出席欧洲经贸峰会“大进步日”
大数据·人工智能·物联网
治愈系科普3 小时前
数字化种植牙企业
大数据·人工智能·python
AI数据皮皮侠3 小时前
中国植被生物量分布数据集(2001-2020)
大数据·人工智能·python·深度学习·机器学习
重生之绝世牛码3 小时前
Linux软件安装 —— PostgreSQL集群安装(主从复制集群)
大数据·linux·运维·数据库·postgresql·软件安装·postgresql主从集群