分布式搜索引擎-ES-进阶

分布式搜索引擎-ES

一、文档乐观锁控制

1.版本7.2以前
版本7.2以前ES根据version来做乐观锁控制
(1) 更新文档的部分数据
格式:post请求 – http://192.168.43.8:9200/索引库名称/_doc/文档id?version=版本号
请求体中数据:

{
	"doc": {
		"name": "study-2",
		"desc": "study is very good, 学习非常优秀!!"
	}
}

(2) 更新文档的所有数据
格式:post请求 – http://192.168.43.8:9200/索引库名称/_doc/文档id?version=版本号
请求体中数据:

{

	"name": "study-2",
	"desc": "study is very good, 学习非常优秀!!"
	...文档的所有字段
}

2.版本7.2以后
版本7.2以后ES根据seq_no 和 primary_term 来做乐观锁控制
seq_no 相当于学号
primary_term相当于班级
每次更新seq_no都会累加,初始值为1
(1) 更新文档的部分数据
格式:post请求 – http://192.168.43.8:9200/索引库名称/_doc/文档id?if_seq_no=对应序列号&if_primary_term=对应值
请求体中数据:

{
	"doc": {
		"name": "study-2",
		"desc": "study is very good, 学习非常优秀!!"
	}
}

(2) 更新文档的所有数据
格式:post请求 – http://192.168.43.8:9200/索引库名称/_doc/文档id?if_seq_no=对应序列号&if_primary_term=对应值
请求体中数据:

{

	"name": "study-2",
	"desc": "study is very good, 学习非常优秀!!"
	...文档的所有字段
}

二、分词与内置分词器

默认分词器只支持英文
请求方式
post请求:http://192.168.43.8:9200/_analyze
请求体数据为:

{
	"analyzer":"standard",
	"text":"I Study in every day"
}

分词结果:i、 study、 in、 every、 day
大写会默认转换为小写
5种内置分词器
1.standard:标准分词器(默认),特点——>会将所有单词分解出来,并且字母默认转换为小写;
2.simple:按照非字母进行差分,例如don’t会拆分为 don t,同样字母默认转换为小写;
3.whitespace:按空格进行切分,例如 I study in,every day not don’t 将会被分解为 i、 study、 in, every、 day、 not 、don’t ,注意in, every被分解为了一个单词;
4.stop:正常分解,但是会去掉语句中的冠词,例如 I study in the every day 将会被分解为 i、 study、 every 、day;
5.keyword:一整段会被认为是一个单词,不会进行任何才分;

三、ik分词器插件

安装包:https://github.com/medcl/elasticsearch-analysis-ik/releases
源码:https://github.com/medcl/elasticsearch-analysis-ik

1.安装
(1)上传elasticsearch-analysis-ik-7.4.2.zip 到服务器
(2)通过unzip解压文件(unzip elasticsearch-analysis-ik-7.4.2.zip -d /usr/local/elasticsearch-7.4.2/plugins/ik)
(3)elasticsearch服务

2.分词器
ik_max_word:只要是单词就会分解,分解细粒度较小
ik_smart:分解语句时细粒度较小

3.自定义中文词库
(1)修改配置文件
IKAnalyzer.cfg.xml 文件所在位置, 一般在es安装目录下 conf/analysis-ik/config/IKAnalyzer.cfg.xml 或者在es安装目录下plugins/elasticsearch-analysis-ik-*/config/IKAnalyzer.cfg.xml
文件内容如下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>IK Analyzer 扩展配置</comment>
	<!--用户可以在这里配置自己的扩展字典 -->
	<entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry>
	 <!--用户可以在这里配置自己的扩展停止词字典-->
	<entry key="ext_stopwords">custom/ext_stopword.dic</entry>
 	<!--用户可以在这里配置远程扩展字典 -->
	<entry key="remote_ext_dict">location</entry>
 	<!--用户可以在这里配置远程扩展停止词字典-->
	<entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>
</properties>

修改<entry key="ext_dict">自定义词库所在的本地路径</entry>
重启es服务即可生效
详情参见:https://github.com/medcl/elasticsearch-analysis-ik

四、DEL搜索

1.入门语法
(1)基于路径构建请求(QueryString)
get请求:http://192.168.43.8:9200/索引库名称/_search?q=字段名1:搜索内容1&q=字段名2:搜索内容2
(2)结构化查询(DSL)
post请求 http://192.168.1.6:9200/索引库名称/_doc/_search
请求体内容:

{
	"query":{
		"match":{
			"字段名":"学习"
		}
	}
}

判断某个字段是否存在,代码如下:

{
	"query":{
		"exists":{
			"field":"字段名"
		}
	}
}

2.查询所有与分页
(1)基于路径构建请求–查询所有(QueryString)
get请求:http://192.168.1.6:9200/索引库名称/_doc/_search
(2)结构化查询(DSL)
post请求 http://192.168.1.6:9200/索引库名称/_doc/_search
请求体内容:

{
	"query":{
		"match_all":{}
	}
}

返回字段筛选,如下,只返回id和username

{
	"query":{
		"match_all":{}
	},
	"_source":[
		"id",
		"username"
	]
}

分页:

{
	"query":{
		"match_all":{}
	},
	
	"from": 起始位置,
	"size": 条数
}

3. term与match

term(关键字不会被分词):

{
	"query":{
		"term":{
			"字段名":"关键字"
		}
	}
}

terms(关键字不会被分词):

{
	"query":{
		"terms":{
			"字段名":["关键字1","关键字2","关键字3"]
		}
	}
}

4. match_phrase

{
	"query":{
		"match_phrase":{
			"字段名":{
				"query": "关键字1 关键字2",
				"slop": slop默认为0,为0,表示关键字1和关键字2必须连贯,为1时表示关键字1和关键字2中间可隔1个词,以此类推
			}
			
		}
	}
}

其他如:

{
	"query":{
		"match_phrase":{
			"字段名":{
				"query": "网站 学习 到了",
				"slop":10
			}
		}
	}
}

4. match(operator)与ids

operator 关键字:

{
	"query":{
		"match":{
			"字段名":{
				"query": "搜索内容",
				"operator":"and"
			}
			
		}
	}
}

上述关键字"operator"如果为or的话,表明结果只要匹配搜索内容分词后的其中一条即可;
"operator"如果为or的话,表明结果需要匹配搜索内容分词后的所有关键字;

minimum_should_match 关键字:

{
	"query":{
		"match":{
			"字段名":{
				"query": "搜索内容",
				"minimum_should_match":"60%"
			}
			
		}
	}
}

上述关键字"minimum_should_match"如果为x%的话,表明结果至少包含搜索内容分词后的x%个单词;
"minimum_should_match"如果为数字n的话,表明结果至少需要包含搜索内容分词后的n个单词;

ids 关键字:

{
	"query":{
		"ids":{
			"type": "_doc",
			"values":["id1","id2"]					
		}
	}
}

5.multi_match与boost

以多个字段作为搜索对象(按默认权重排序,倒叙)

{
	"query":{
		"multi_match":{
			"query": "搜索内容",
			"fields":["字段1","字段2"]					
		}
	}
}

以多个字段作为搜索对象(按指定权重排序,倒叙)

{
	"query":{
		"multi_match":{
			"query": "搜索内容",
			"fields":["字段1^权重1","字段2^权重2"]					
		}
	}
}

6.布尔查询
(1)关键字 must

{
	"query": {
		"bool": {
			"must": [
				{
					"term": {
						"字段1": "搜索内容"
					}
				},
				{
					"term": {
						"字段2": "搜索内容"
					}
				}
			]
		}
	}
}

上述条件,必须满足关键字"must"中的每一个条件

(2)关键字 should

{
	"query": {
		"bool": {
			"should": [
				{
					"term": {
						"字段1": "搜索内容"
					}
				},
				{
					"term": {
						"字段2": "搜索内容"
					}
				}
			]
		}
	}
}

上述条件,只要满足关键字"should"中的任意一个条件即可

(3)关键字 must_not

{
	"query": {
		"bool": {
			"must_not": [
				{
					"term": {
						"字段1": "搜索内容"
					}
				},
				{
					"term": {
						"字段2": "搜索内容"
					}
				}
			]
		}
	}
}

上述条件,不满足关键字"must_not"中的所有
(4)关键字 must,must_not,should联用

{
	"query": {
		"bool": {
			"must": [
				{
					"term": {
						"字段1": "搜索内容"
					}
				},
				{
					"term": {
						"字段2": "搜索内容"
					}
				}
			],
			"must_not": [
				{
					"term": {
						"字段3": "搜索内容"
					}
				}
			],
			"should": [
				{
					"term": {
						"字段4": "搜索内容"
					}
				}
			]
		}
	}
}

上述内容,表示必须满足must的条件,并且不包含must_not中条件,或者在此基础上满足should中的任一条件

(4)关键字 boost(加权)

{
	"query": {
		"bool": {
			"must": [
				{
					"match": {
						"字段名1": {
							"query":"大家的环境",
							"boost":10
						}
					}
				},
				{
					"term": {
						"字段名2": "0"
					}
				}
			]
		}
	}
}

7.过滤器

{
	"query": {
		"match":{
			"字段名1":"搜索内容"
		}
	},
	"post_filter":{
		"range":{
			"字段名2":{
				"gte":66, #指大于等于66
				"lt":1000 #小于1000
			}
		}
	}
}

gt:大于(greater than)
lt:小于(less than)
gte:大于等于(greater than equals)
lts:小于等于(less than equals)

8.排序

{
	"query": {
		"match":{
			"字段名":"搜索内容"
		}
	},
	"sort":[
		{
			"字段名1":"asc"
		},
		{
			"字段名2":"desc"
		}
	]
}

asc:升序
desc:降序
9.高亮-highLight

{
	"query":{
		"match":{
			"字段名":"搜索内容"
		}
	},
	"highlight":{
		"pre_tags":["<span>"],
		"post_tags":["</span>"],
		"fields":{
			"字段名":{}
		}
	}
}

pre_tags:前缀,post_tags:后缀,包裹分词后的搜索内容,用以高亮显示;也可以不用这两个关键字,不用则以<em></em>包裹

五、进阶操作

1.深度分页
(1)概念
ES搜索数据范围过广(一般from的值过大)时,称之为深度分页;搜索数据超过10000条时,会报错(illegal_argument_exception)。
(2)语法
post请求,http://192.168.1.6:9200/索引库名称/_doc/_search

{
	"query":{
		"match_all":{
			
		}
	},
	"from": 9999,
	"size":10
}

如上,我们在获取9999至10009区间的数据时,实际上每个分片拿到的是10009条,然后将每个分片获取到的数据合并,合并之后再排序,最终会获得最后的10条数据。这样的话,搜索太深,性能影响很大,一般情况而言,我们会避免深度分页操作,限制分页页数。
(3)查询ES深度搜索限制
get请求 http://192.168.1.6:9200/shop/_settings
(4)修改ES深度搜索限制
put请求 http://192.168.1.6:9200/索引名称/_settings
请求体中参数

{
"index.max_result_window":限制条数
}

2.滚动搜索
第一步:初始化查询
post 请求 http://192.168.1.6:9200/索引库名/_search?scroll=1m
参数scroll 表示滚动查询会话保持时间
请求体:

{
	"query":{
		"match_all":{
			
		}
	},
	"sort": "_doc",
	"size":10
}

sort:表示操作类型,"sort": "_doc"表示文档操作
size:表示每页大小
第二步:批量获取
post 请求 http://192.168.1.6:9200/_search/scroll

{
    "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAJ9Fm13STJuYW0tVDd5SjdoNjY2aGpHdUEAAAAAAAACgRZtd0kybmFtLVQ3eUo3aDY2NmhqR3VBAAAAAAAAAn4WbXdJMm5hbS1UN3lKN2g2NjZoakd1QQAAAAAAAAJ_Fm13STJuYW0tVDd5SjdoNjY2aGpHdUEAAAAAAAACgBZtd0kybmFtLVQ3eUo3aDY2NmhqR3VB",
    "scroll":"1m"
}

scroll_id :指上次请求返回的结果_scroll_id,当没有结果返回时,就意味着批次处理完毕;
scroll:滚动查询会话保存时间
注意:尽管我们每次查询指定size为某个值,如1000,但实际上我们可能取到超过这个值的文档,当查询时,size作用于每个单分片,所以每个批次实际返回的文档数量最大为size*number_of_primary_shards。
3.批量查询
post请求 http://192.168.1.6:9200/索引库名称/_doc/_mget
请求体:

{
    "ids":["1001","1005"]
}

mget与search
用search查多个:
post请求 http://192.168.1.6:9200/索引库名称/_doc/_search

{
	"query":{
		"ids":{
			"type":"_doc",
			"values":["1001","1005"]
		}
	}
}

他们之间除了查询方式迥异,返回结果也有所差异,感兴趣的话,可以自行测试。
4.批量操作
(1)bulk-create
post请求 http://192.168.1.6:9200/_bulk

{"create":{"_index":"索引库名称","_type":"_doc","_id":"2004"}}
{"id":"2004","nickname":"name-2004"}
{"create":{"_index":"索引库名称","_type":"_doc","_id":"2005"}}
{"id":"2005","nickname":"name-2005"}
{"create":{"_index":"索引库名称","_type":"_doc","_id":"2003"}}
{"id":"2003","nickname":"name-2003"}

id和nickname都是文档中的字段
注意:请求体需要以换行(\r\n)结尾
请求体中的_index参数和_type参数也可以直接放在路径上(http://192.168.1.6:9200/索引库名称/_doc/_bulk),如果这两个参数放在路径上,请求体中就不需要再写这两个参数了,下面介绍index时,会使用到这种格式
(2)bulk-index
post请求 http://192.168.1.6:9200/shop2/_doc/_bulk

{"index":{"_id":"2004"}}
{"id":"2004","nickname":"index-2004"}
{"index":{"_id":"2007"}}
{"id":"2007","nickname":"name-2007"}
{"index":{"_id":"2008"}}
{"id":"2008","nickname":"name-2008"}

index和create的区别在于,index是没有这条数据就创建,有就覆盖;create时没有就创建,有就失败(只失败这一条,其他正常创建)。
(3)bulk-update、delete
update
post请求 http://192.168.1.6:9200/shop2/_doc/_bulk

{"update":{"_id":"2004"}}
{"doc":{"id":"3306"}}
{"update":{"_id":"2016"}}
{"doc":{"id":"2016","name":"name-2016"}}

delete
post请求 http://192.168.1.6:9200/shop2/_doc/_bulk

{"delete":{"_id":"2009"}}
{"delete":{"_id":"2018"}}

注意:这几种操作是可以放在一次请求里的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值