全文搜索
全文搜索是应用到字段类型为text
上的搜索,也是es重要特性,es会根据字段的分词器算法,把字段进行解析,根据解析后的结果在es服务器中利用倒排索引算法,获取多个文档,并给出相应的得分。
搜索和过滤的区别
- 搜索要给出每个文档得分
- 过滤不计算每个文档得分,而且过滤会把数据缓存起来。
全匹配
全部匹配,每个文档得分都是1
GET myindex/_search
{
"query": {
"match_all": {
}
}
}
全部不匹配
GET myindex/_search
{
"query": {
"match_none": {
}
}
}
1.Match Query
match是只要文档包含任何一个分词,都要返回(分词间没有顺序依赖)
match是一个布尔查询,可能这句话不太了解这句话的含义。这是因为通常我们看到的查询语句的写法是下例:
GET myindex/_search
{
"query": {
"match": {
"addr":"hangzhou shenzhen"
}
}
}
其实上面的简写的语法,真正的语法格式是下面:
GET myindex/_search
{
"query": {
"match": {
"addr": {
"query" :"hangzhou shenzhen",
"operator" : "or"
}
}
}
}
所以match有很多属性,就是在这里定义的,上例表示addr
只要有hangzhou
,shenzhen
任何一个词元都要返回文档。
响应的结果:
"hits": {
"total": 2,
"max_score": 0.25316024,
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 0.25316024,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
},
{
"_index": "myindex",
"_type": "mytype",
"_id": "1",
"_score": 0.25316024,
"_source": {
"name": "mayun",
"age": "43",
"addr": "zhongguo zhejiang hangzhou",
"city": "hangzhou"
}
}
]
}
如果把"operator" : "or"
改为"operator" : "and"
则不会返回文档。
同样还有很多其他的属性:
- query:实际被解析的语句
- operator:操作符,“and” 或者 “or”,默认是"or"
- lenient:布尔值,默认false,表示格式配置失败是否失败(例如用字符串查整型字段)
- minimum_should_match:或逻辑,最小要匹配几个逻辑
- analyzer:分词器
- zero_terms_query : 文档只有停顿词,是否返回,默认是
none
, 还有all
- max_expansions:是指可以扩展最大词项。
- fuzziness:设置模糊性,默认是
AUTO
还有很多其他的属性,就不介绍了
下面重点说下fuzziness
模糊性的用法,因为对于英文语法有词根,词缀的语法,所以一个单词可以有多种变形,所以模糊性搜索就变得很常用了。(对于中文这种用法就没用了)
根据官网解释:
fuzziness is interpreted as a Levenshtein Edit Distance — the number of one character changes that need to be made to one string to make it the same as another string.
就是从一个单词变成另一个单词需要编辑的次数。
fuzziness
有两种表示方式:
- 0 或 1 或 2,表示编辑距离(可以大于2,但是和2作用一样)
- AUTO :是一个算法。
目标单词长度为 0 到 2 之间时,必须要精确匹配
目标单词长度为 3 到 5 之间时,最大编辑距离为 1
目标单词长度大于5,最大编辑距离为 2
举个栗子:用said去查say是查不到的,因为最大编辑距离是2才能找到。 - 另外还可以设置前缀不能模糊的长度
prefix_length
。
match最基础的全文索引语法,所以其他的语法,都是在此基础上扩展的。(通过使用不同的参数可以构建其他的检索语法)
2.Match Phrase Query
match_phrase的分词结果必须在被检索字段的分词中都包含,而且顺序必须相同,而且默认必须都是连续的。
GET myindex/_search
{
"query": {
"match_phrase": {
"addr": "zhongguo guangdong"
}
}
}
例如上例:返回文档中,addr
中必须包含zhongguo
和guangdong
而且他们的顺序是不变的,也要保证他们之间没有其他的有效词。
返回结果:
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 0.82712996,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
},
{
"_index": "myindex",
"_type": "mytype",
"_id": "1",
"_score": 0.5063205,
"_source": {
"name": "renzhenfei",
"age": "71",
"addr": "zhongguo guangdong guangzhou",
"city": "guangzhou"
}
}
]
短语查询有个重要参数:slop
,可以容忍查询词之间位置跳过位置,默认值为0(注意:之间的跳跃位置的范围是[0, slop],并不是必须跳过slop个位置)
注意:如果要使用参数,就不能使用简易语法了。
例如:
GET myindex/_search
{
"query": {
"match_phrase": {
"addr": {
"query" :"zhongguo shenzhen",
"slop" : 3
}
}
}
}
返回的文档:可以发现,zhongguo shenzhen
之间只有一个guangdong
。
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 0.5266491,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
}
]
3.Match Phrase Prefix Query
是对match_phrase
的扩充,只是会对查询文本的分词后最后一个分词,可以前缀模糊查询。
有个重要的参数max_expansions
可以指定模糊度[0, max_expansions]。
例如:
GET myindex/_search
{
"query": {
"match_phrase_prefix": {
"addr": {
"query" :"zhongguo guangdong shen",
"max_expansions" : 10
}
}
}
}
返回的结果是:
"hits": [
{
"_index": "myindex",
"_type": "mytype",
"_id": "2",
"_score": 1.4820052,
"_source": {
"name": "mahuateng",
"age": "40",
"addr": "zhongguo guangdong shenzhen",
"city": "shenzhen"
}
}
]
但是我发现下面的语法也能返回上述结果:(如果哪位大神指导为什么,也可以评论告知)
GET myindex/_search
{
"query": {
"match_phrase_prefix": {
"addr": {
"query" :"zhongguo guangdong shen",
"max_expansions" : 1
}
}
}
}
4.Multi Match Query
multi_match
查询建立在match
查询之上,重要的是它允许对多个字段查询。
GET /_search
{
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
}
multi_match
内部如何执行是由参数type
决定的。下面是type
的可选值
best_fields
:默认方式,会将任何与查询匹配的文档作为结果返回,但是只使用最佳字段的 _score 评分作为评分结果返回。(使用场景是查询文档含有多个有效词,一个文档同时含有多个有效词要比只含有一个有效词的文档得分高)。most_fields
:会将任何与查询匹配的文档作为结果返回,但是所有字段的评分合并起来作为评分结果返回。cross_fields
:将查询字符串分词后每个分词,在查询的字段中都去查询每个分词(当要求多个字段都应该查询到的时候适合该方式)phrase
:和best_fields
相似,只是内部使用的是match_phrase
。phrase_prefix
:和best_fields
相似,只是内部使用的是match_phrase_prefix
。