学习elasticsearch

一、初识

  • 1、概念:
    • elasticsearch是一款强大的开源搜索引擎,可以从海量数据中快速找到需要的内容。
    • 使用:elasticsearch(存储,计算,搜索数据)可以结合kibana(数据可视化)Logstash、Beats(数据抓取)一起使用
  • 2、原理:
    • 正向索引(传统数据库):
     select * from tb_goods where title like '%手机%'
      # tb_goods中逐行搜索 title中包含手机的数据。找到存入结果集;找不到丢弃
    
    • 倒排索引(elasticsearch):
       # 搜索有包含手机的文档
       # 原理:根据正向索引生成倒排索引[词条,文档id];1、对用户输入进行分词 2、根据分词检索词条列表 3、根据词条列表对应的文档id 查询数据 4、将符合条件的输入存入结果集
    
idtitleprice
华为电脑$16009999
华为手机$12999
导管$19
词条文档id
电脑1
手机2
导管3
华为1、2
搜索 ''安卓手机''
得到 '安卓','手机'两个词条
得到文档id 2
用户输入
分词对用户输入内容进行分词
去词条列表查询
根据文档id 查询文档
存入结果集
  • 3、名词解释:

    • 索引:Index 类似数据库的表
    • 文档:Document 类似数据库的一行数据
    • 字段:Field 类似数据库的字段
    • 映射:Mapping 类似数据库字段的约束
    • DSL:json格式的请求语句,类似SQL语句
  • 4、简单使用
    (1)停用某些分词:修改ik分词器目录中的config–IkAnalyzer.cfg.xml文件,在IK Analyzer 扩展配置中,ext_dict配置自己的扩展字典;ext_stopwords配置自己扩展停用词字典
    (2)mapping属性

    • type:字段数据类型
      • 字符串 text(可分词的文本)、keyword(精确值,不分词)
      • 数值 long、integer、short、byte、double、float
      • 布尔 boolean
      • 日期 date
      • 对象 object
    • index:是否创建索引,默认为true
    • analyzer:指定分词器
    • properties:该字段的子字段

    (3)操作索引库

	# 创建索引库
	PUT /索引库名称
	{
		"mappings": {
			"properties": {
				"字段名1":{
					"type": "text",
					"analyzer":"ik_smart"
				},
				"字段名2":{
					"type": "keyword",
					"index":"false"
				},
				"字段名3":{
					"properties": {
						"子字段": {
							"type": "keyword"
						}
					}
				},
				# 省略
			}
		}
	}
	
	# 查看索引库
	GET /索引库名
	
	# 删除索引库
	DELETE /索引库名
	
	# 修改索引库
	PUT /索引库名/_mapping{
		"properties":{
			"新字段名":{
				"type": "integer"
			}
		}
	}
	

(4)操作文档

	# 新增文档 (文档id不能省)
	POST /索引库名/_doc/文档id{
		"字段1": "值1",
		"字段2": "值2",
		"字段3": {
			"子属性1""值3",
			"子属性2""值4"
			
		},
	}
	
	# 查看文档
	GET /索引库名/_doc/文档id
	
	# 删除文档
	DELETE /索引库名/_doc/文档id
	
	# 修改文档  1、全量修改 2、增量修改
	PUT /索引库名/_doc/文档id{
		"字段1": "值1",
		"字段2": "值2",
		# 省略
	}
	
	POST /索引库名/_update/文档id{
		"doc": {
			"字段名": "新的值",
		}
	}

(5)地理坐标类型

  • geo_point:由纬度和经度确定一个点"12.1234567, 120.1234567"
  • geo_shape:由多个geo_point组成复杂几何图形(12.4567894 23.1234567, 2.7654321 4.7654321)

(6)多参数搜索

  • 字段拷贝:使用copy_to属性将当前字段拷贝到指定字段
	"all":{
		"type": "text",
		"analyzer": "ik_max_word"
	},
	"brand":{
		"type": "keyword",
		"copy_to": "all"
	}

二、查询语句

1、查询分类
  • 查询所有:查询所有数据,一般测试使用 match_all
	GET /IndexName/_search
	{
		"query":{
			"match_all":{
				"查询条件": "条件值"
			}
		}
	}
  • 全文检索:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。
    • match_query:根据一个字段去查询
    • multi_match_query:根据多个字段去查询,查询字段越多,性能越差
	GET /indexName/_search
	{
		"query":{
			"match":{
				"FIELD":"TEXT"
			}
		}
	}
	
	GET /indexName/_search
	{
		"query":{
			"multi_match":{
				"query":"TEXT",
				"fields":["FIELD1","FIELD2"]
			}
		}
	}
  • 精确查询:利用精确词条值查找数据,一般查找keyword。
    • ids、range、term
	# 根据term查询
	GET /indexName/_search
	{
		"query":{
			"term":{
				"FIELD":{
					"value": "VALUE"
				}
			}
		}
	}
  • 地理查询:根据经纬度查询。
    • geo_distance:查询到指定中心点小于某个距离值的所有文档
    • geo_bounding_box:查询geo_point值落在某个矩形范围的所有文档
GET /indexName/_search
{	
	"query":{
		"geo_distance":{
			"distance":"15km",
			"FIELD":"44.5,151.2"
		}
	}
}

GET /indexName/_search
{	
	"query":{
		"geo_bounding_box":{
			"FIELD":{
				"top_left":{
					"lat"15.2:,
					"lon"98.4,
				},
				"bottom_right":{
					"lat"30.5:,
					"lon"40.3,
				}
			}
		}
	}
}
  • 复合查询:将上述各种查询条件组合起来,合并查询条件。

    相关性算分 :
    TF(词条频率) = 词条出现次数/文档中词条总数 //一个文档的词条频率越高,相关性越高

    TF-IDF算法
    IDF(逆文档频率) = Log(文档总数/包含词条的文档总数)//词条在文档中出现的频率越少说着这个词条的权重越高
    s c o r e = ∑ i = 1 n ( T F ∗ I D F ) score =\sum_{i=1}^{n} (TF*IDF) score=i=1n(TFIDF)
    缺点:会随着词频增加而越来越大

    BM25算法
    S c o r e ( Q , d ) = ∑ i = 1 n l o g ( 1 + N − n + 0.5 n + 0.5 ) ∗ f   i f   i + k   1 ∗ ( 1 − b + b ∗ d l a v g d l ) Score(Q,d) =\sum_{i=1}^{n} log(1+{\frac{N-n+0.5}{n+0.5}}) *{\frac{f~i}{f~i+k~1*(1-b+b*\frac{dl}{avgdl})}} Score(Q,d)=i=1nlog(1+n+0.5Nn+0.5)f i+k 1(1b+bavgdldl)f i
    会随着词频增加,逐渐趋于平缓

    • function_score:算分查询函数,控制文档相关性算分,进而控制文档排序
    • BooleanQuery:一个或多个查询子句的组合。子查询的组合方式:必须匹配;选择匹配;必须不匹配,不参与算分;必须匹配,不参与算分【算分会影响性能】
# function_score
GET /hotel/_search
{
	"query":{
		"function_score":{
			"query": {"match": {"all""外滩"}},  # 原始查询条件,根据打分规则打分
			"functions":[
				{
					"filter": {"term": {"id": "1"}}, # 过滤需要被重新打分的文档
					"weight":10  # 算分函数(结果为function score):1、weight 给一个常量值,作为函数结果function score;2、field_value_factor 用文档中某个字段值作为函数结果;3、random_score:随机生成一个值,作为函数结果;4、script_score:自定义计算公式
				}
			],
			"boost_mode": "multiply" # 加权模式,定义function score与query score的运算方式。1、multiply 两者相乘(默认);2、replace 使用function score 代替query score 3、其他:sum、avg、max、min
		}
	}
}

# BooleanQuery
GET /hotel/_search
	{
		"query":{
			"bool":{
				"must":[
					{"term": {"city": "上海"}}
				],
				"should":[
					{"term": {"brand": "皇冠假日"}},
					{"term": {"brand": "华美达"}}
				],
				"must_not":[
					{"range": {"price": {"lte":500}}}
				],
				"filter":[
					{"range": {"score": {"gte":45}}}
				]
			}
		}
	}
2、搜索结果处理
  • es支持对搜索结果排序,支持的排序字段:keyword、数值、地理坐标、日期
GET /indexName/_search
{
"query":{
	"match_all": {}
},
"sort":[
	{
		"FIELD": "desc"  # 排序字段:排序方式
	}
]
}
# 地理坐标排序
GET /indexName/_search
{
"query":{
	"match_all": {}
},
"sort":[
	{
		"_geo_distance": {
			"FIELD": "纬度,经度", # 字段:中心点经纬度
			"order": "asc"
			"unit": "km"
		}  
	}
]
}
  • es 通过修改from、size参数来控制要返回的分页结果【搜索页数过深,结果集越大,对内存和CPU的消耗越高】
	GET /indexName/_search
	{
		"query":{
			"match_all": {}
		},
		"from": 990,  # 分页开始的位置,默认为0
		"size": 10,		# 期望获取的分页总数
		"sort":[
			{"price": "asc"}
		]
	}
  • es 高亮显示:在搜索结果中把搜索关键字突出显示
	# 原理:将搜索结果中的关键字用标签标记出来;在页面中给标签添加css样式
	GET /hotel/_search
	{
		"query": {
			"match": {    # 不能用match_all
				"FIELD": "TEXT"
			}
		},
		"highlight": {
			"fields":{
				"FIELD": {   # 指定要高亮的字段
					"pre_tags": "<em>",  # 标记高亮字段的前置标签
					"post_tags": "</em>" # 标记高亮字段的后置标签
				}
			}
		}
	}
	

三 、数据处理

1、数据聚合
  • 聚合概念:实现对文档数据的统计、分析、运算,常见有三个分类:
    • 桶(Bucket)聚合::用来对文档进行分组(term、date 等等),默认是对所有文档进行聚合
    • 度量(Metric)聚合:计算一些值(Avg、Max、Min、Stats)
    • 管道(pipeline)聚合:以其他聚合的结果为基础再做聚合
  • 注意事项:参与聚合的字段一定不能是分词的字段
# 限定范围的聚合和嵌套聚合
GET /hotel/_search
{
	# 查询价格低于200的酒店
	"query": {
		"range": {
			"price": {
				"lte" :200
			}
		}
	},
	"size":0,	# 结果中不包含文档,只包含聚合结果
	"aggs": {
		"brandAgg": { # 自定义名称
			"terms": {  # 聚合类型
				"field": "brand", # 聚合字段
				"size": 20  # 聚合结果的数量
				"order": {
					"_count": "asc" # 指定显示顺序 asc/desc
				}
			}
		},
		# 根据品牌聚合后的结果对每个品牌求最小、最大、平均、求和
		"aggs": {
			"scoreAgg": { # 自定义名称
				"stats": { # 聚合类型
					"field": "score"  # 聚合字段
				}
			}
		}
	}
}
2、自动补全
  • 分词器的组成分为三部分:
    • character filters : 在tokenizer之前对文本进行处理,例如删除、替换字符
    • tokenizer:将文本按照一定的规则切割成词条(term)
    • tokenizer filter:将tokenizer输出的词条做进一步处理。大小写转换、同义词处理、拼音处理
	PUT /test
	{
		"settings": {
			"analysis": {
				"analyzer": { # 自定义分词器
					"my_analyzer": {  # 分词器名称
						"tokenizer": "ik_max_word",
						"filter": "py"  # 由于py不是规定的过滤器类型,所以会向下找定义 py过滤器的地方
					}
				},
				"filter":{  # 自定义tokenizer filter
					"py": {  # 过滤器名称
						"type": "pinyin", # 过滤器类型
						"keep_full_pinyin": false,
						"keep_joined_full_pinyin": true,
						"keep_original": true,
						"limit_first_letter_length": 16,
						"remove_duplicated_term": true,
						"none_chinese_pinyin_tokenize": false
					}
				}
			}
		}
	}
  • 拼音分词器适合在创建倒排索引时使用,不能在搜索时使用
PUT /test
	{
		"settings": {
			"analysis": {
				"analyzer": { # 自定义分词器
					"my_analyzer": {  # 分词器名称
						"tokenizer": "ik_max_word",
						"filter": "py"  # 由于py不是规定的过滤器类型,所以会向下找定义 py过滤器的地方
					}
				},
				"filter":{  # 自定义tokenizer filter
					"py": {  # 过滤器名称
						"type": "pinyin", # 过滤器类型
						.....}
				}
			}
		},
		
		"mappings": {
			"properties":{
				"name": {
					"type": "text",
					"analyzer": "my_analyzer",  # 创建索引时使用的分词器
					"search_analyzer": "ik_smart" # 搜索时使用的分词器
				}
			}
		}
	}

四 、结束

内容来源:https://www.bilibili.com/video/BV1Gh411j7d6/?spm_id_from=333.337.search-card.all.click

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值