学习须要先打好基础,最后才能逐步深刻。今天来从新探索下ElasticSearch
的全文搜索。web
ElasticSearch中存在两种搜索方式。一种是Request Body Search
和Request URL Search
方式。Request URL Search
是经过将参数放在URL
以后来达到传递查询语句的目的,好比算法
GET /GET /kibana_sample_data_ecommerce/_search?q=customer_first_name:Eddie
复制代码
另一种是Request Body Search
是经过将参数以json
串的方式传递,相对于Request URL Search
来讲更加清晰,更够传递更加复杂的参数。通常在实际的使用中,Request Body Search
会使用的多一些。下面主要讲一讲Request Body Search
的方式来查询ElasticSearch
。json
本文使用的数据均为kibana
中的kibana_sample_data_ecommerce
数据。bash
在ElasticSearch
的查询API中存在两种主要的过滤方式。一种是Query
,由query
引导。另一种是filter
,由filter
来引导。二者之间的区别是在query
以后的查询子句,会对文档的分数产生影响。而filter
以后的查询子句不会对文档的分数产生影响。学习
举个例子。测试
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"customer_first_name": "Eddie"
}
}
],
"filter": {
"term": {
"customer_full_name.keyword": "Eddie Underwood"
}
}
}
}
}
复制代码
能够看到该bool
查询存在match
和term
子查询。由于term
在filter
对象内,因此不会对最后的排序分数产生影响。而match
子查询中的customer_first_name
会对最后的排序分数产生影响。网站
match_all
做为最简单的查询。通常不会在生产环境中使用,在测试环境中使用的会较多。match_all
会查询出全部的文档。 举个例子。搜索引擎
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_all": {}
}
}
复制代码
今天才发现竟然存在这么个搜索。match_none
是match_all
的反面,不会搜索到任何的文档。spa
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_none": {}
}
}
复制代码
做为一个全文搜索引擎的意义,对于text
字段使用全文搜索。最典型的应用是能够用来搜索文章(好比各大博客网站),用来搜索代码(好比Github)。code
match
查询是最典型的全文搜索的查询子句。match
查询子句会将查询语句根据字段的分析器分析为多个单词。而后逐个查询文档中该字段是否存在。 举个例子。
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match": {
"customer_full_name": "Eddie Weber"
}
}
}
复制代码
能够获得
"hits" : {
"total" : 115,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
}
]
复制代码
customer_full_name
会被分析为eddie
和weber
两个单词。以后在文档中的customer_full_name
中查询是否包含这两个字段。若是包含了这两个单词其中一个,那么就算是匹配成功。若是一个都没有包含,那么就表示匹配不成功。在示例数据中eddie
或者weber
匹配到了115个文档。
默认状况下匹配的算法的确跟上面同样,只要包含了一个单词就能够匹配上文档。可是,也能够经过参数operator
来修改这个算法。好比下面指定and
操做符。
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match": {
"customer_full_name": {
"query": "Eddie Weber",
"operator": "and"
}
}
}
}
复制代码
只能匹配上两个文档。从原来的匹配115个文档降到了2个文档。
"hits" : {
"total" : 2,
"hits" : [
"_source" : {
"customer_full_name" : "Eddie Weber",
复制代码
这里表示必须customer_full_name
必须既包含eddie
也要包含weber
才能够匹配上。
match Phrase
表示短语搜索。当咱们想要搜索一个短语的时候,可使用match Phrase Query
,好比咱们仍是想要搜索customer_full_name
为Eddie Webber
的人。可是,咱们不想搜索出来只叫作Eddie
,也不想搜索出来叫作Eddie xxx Webber
的人。这个时候可使用match Phrase
,由于match Phrase
不只会要求字段内容中均包含eddie
和webber
也要求这两个单词的顺序是一致的,中间不能有其余单词插入。
好比咱们再插入一条数据,一个叫作Eddie fake Weber
的人。
POST /kibana_sample_data_ecommerce/_doc/1
{
"customer_full_name":"Eddie fake Weber"
}
复制代码
这个时候,使用match
和and
来进行匹配会发现有三条数据。
"hits" : {
"total" : 3,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name":"Eddie Weber"
},
{
"customer_full_name":"Eddie fake Weber"
}
复制代码
咱们使用match Phrase Query
来进行搜索。
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase": {
"customer_full_name": "Eddie Weber"
}
}
}
复制代码
就只会获得只有名字叫作Eddie Weber
的人。
"hits" : {
"total" : 2,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name" : "Eddie Weber"
}
复制代码
ElasticSearch
中还提供了一个叫作slop
的参数。使用slop
参数能够指定单词之间的最大间隔是多少。间隔指短语中单词与单词之间间隔了多少单词。好比上面的Eddie Weber
中的Eddie
和Weber
没有间隔任何的单词,因此间隔为0。而新插入的数据Eddie fake Weber
中的Eddie
和Weber
间隔为1,由于间隔了fake
这个单词。 默认的match phrase
的slop
的值为0。能够设置slop
值为1来匹配上Eddie fake Weber
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase": {
"customer_full_name": {
"query": "Eddie Weber",
"slop": 1
}
}
}
}
复制代码
能够匹配上三个文档。
"hits" : {
"total" : 3,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name":"Eddie Weber"
},
{
"customer_full_name":"Eddie fake Weber"
}
复制代码
和match
搜索比较下能够发现match phrase
相似于match
加上and
条件再加上顺序和间隔为0的条件。
match phrase prefix
跟match phrase
之间的区别是match phrase prefix
可让你在短语的最后一个单词上进行前缀匹配。好比仍是想要搜索customer_full_name
,这个时候我可能已经忘记了Eddie Weber
的最后一个单词Weber
的所有内容了。那么我可使用match phrase prefix
来搜索Eddie We
,由于最后一个单词We
会进行前缀匹配。因此,我仍是可以搜索到Eddie Weber
这我的。 好比
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase_prefix": {
"customer_full_name": "Eddie We"
}
}
}
复制代码
能够匹配上
"hits" : {
"total" : 2,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name" : "Eddie Weber"
}
复制代码
那么不是最后一个单词而是在以前的单词会进行前缀匹配吗? 好比我搜索Edd We
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase_prefix": {
"customer_full_name": "Edd We"
}
}
}
复制代码
匹配不上任何的文档。由于只会对最后一个单词进行前缀匹配。
"hits" : {
"total" : 0,
"max_score" : null,
"hits" : [ ]
}
复制代码
另外ElasticSearch
还提供了max_expansions
来控制最后一个前缀单词和须要匹配的单词之间的距离。什么意思?好比上面使用We
来前缀匹配Weber
。那么这两个单词之间的距离是ber
,也就是3个字母的距离。
加入咱们使用max_expansions
来控制匹配的距离为2,看一下会不会匹配上Weber
?
"百天"写做计划下半部。
每周更新一篇碎碎念。
每周3、周六更新一篇尽可能全面,详细的文章。
可能时长突破了百天,可是又有什么关系呢?提升写做水平,造成写做的习惯才是最终的目的。
若是这篇文章给你带来了一些帮助,能够动动手指点个赞,顺便关注一波就更好了。
若是上面都没有,那么写下读完以后最想说的话?有效的反馈和你的鼓励是对我最大的帮助。
另外打算把博客给从新捡起来了。欢迎你们来访问吃西瓜。
我是shane。今天是2019年9月18日。"百天"写做计划下半部,52/100。