ElasticSearch系列六:深入ES结构化搜索

一、搜索条件的权重boost

默认情况权重都是1,可以将某个搜索条件的权重加大,此时当匹配这个搜索条件和匹配另一个搜索条件的document,计算relevance score时,匹配权重更大的搜索条件的document,relevance score会更高,也就会优先被返回回来。
需求:搜索标题中包含java的帖子,同时呢,如果标题中包含hadoop或elasticsearch就优先搜索出来,同时呢,如果一个帖子包含java hadoop,一个帖子包含java elasticsearch,包含hadoop的帖子要比elasticsearch优先搜索出来。
例:
GET /forum/article/_search 
{
 "query": {
"bool": {
 "must": [
{
 "match": {
"title": "blog"
 }
}
 ],
 "should": [
{
 "match": {
"title": {
 "query": "java"
}
 }
},
{
 "match": {
"title": {
 "query": "spark",
 "boost": 5
}
 }
}
 ]
}
 }
}

二、手动控制全文检索结果的精准度

例1:使用and关键字,所有的搜索关键字都要匹配
GET /forum/article/_search
{
"query": {
"match": {
"title": {
"query": "java elasticsearch",
"operator": "and"
}
}
}
}
例2:指定一些关键字中,必须至少匹配其中的多少个关键字
GET /forum/article/_search
{
  "query": {
"match": {
 "title": {
"query": "java elasticsearch spark hadoop",
"minimum_should_match": "75%"
 }
}
  }
}
或:
GET /forum/article/_search
{
  "query": {
"bool": {
 "should": [
{ "match": { "title": "java" }},
{ "match": { "title": "elasticsearch"   }},
{ "match": { "title": "hadoop"   }},
{ "match": { "title": "spark"   }}
 ],
 "minimum_should_match": 3 
}
  }
}
例3:用bool组合多个搜索条件,来搜索title
GET /forum/article/_search
{
  "query": {
"bool": {
 "must":     { "match": { "title": "java" }},
 "must_not": { "match": { "title": "spark"  }},
 "should": [
 { "match": { "title": "hadoop" }},
 { "match": { "title": "elasticsearch"   }}
 ]
}
  }
}

三、best fields策略dis_max

1.描述:搜索的结果,应该是某一个field中匹配到了尽可能多的关键词,被排在前面;而不是尽可能多的field匹配到了少数的关键词,排在了前面
2.dis_max语法,直接取多个query中,分数最高的那一个query的分数即可
例:
GET /forum/article/_search
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "java solution" }},
{ "match": { "content":  "java solution" }}
]
}
}
}
3.使用tie_breaker将其他query的分数也考虑进去,tie_breaker的值在0~1之间,将其他query的分数,乘以tie_breaker,然后综合与最高分数的那个query的分数,综合在一起进行计算
GET /forum/article/_search
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "java beginner" }},
{ "match": { "content":  "java beginner" }}
],
"tie_breaker": 0.3
}
}
}
4.综合例子:
GET /forum/article/_search
{
  "query": {
"multi_match": {
"query":                "java solution",
"type":                 "best_fields", 
"fields":               [ "title^2", "content" ],
"tie_breaker":          0.3,
"minimum_should_match": "50%" 
}
  } 
}
解释:best_fields策略,title权重为2,tie_breaker为0.3,至少匹配50%的关键词

四、most-fields策略

1.best-fields和most-fields对比:
①best-fields策略,将某一个field匹配尽可能多的关键词的doc优先返回回来
例子:百度之类的搜索引擎,最匹配的到最前面,但是其他的就没什么区分度了
②most-fields策略,尽可能返回更多field匹配到某个关键词的doc,优先返回回来
例子:wiki,明显的most_fields策略,搜索结果比较均匀,但是要翻好几页才能找到最匹配的结果
例:
GET /forum/article/_search
{
 "query": {
"multi_match": {
 "query":       "Peter Smith",
 "type":        "most_fields",
 "fields":      [ "author_first_name", "author_last_name" ]
}
 }
}

五、cross-fields搜索

1.描述:跨了多个field的搜索
2.copy_to,将多个field组合成一个field
PUT /forum/_mapping/article
{
 "properties": {
 "new_author_first_name": {
 "type":     "string",
 "copy_to":  "new_author_full_name" 
 },
 "new_author_last_name": {
 "type":     "string",
 "copy_to":  "new_author_full_name" 
 },
 "new_author_full_name": {
 "type":     "string"
 }
 }
}
3.使用原生cross-fiels
GET /forum/article/_search
{
 "query": {
"multi_match": {
 "query": "Peter Smith",
 "type": "cross_fields", 
 "operator": "and",
 "fields": ["author_first_name", "author_last_name"]
}
 }
}

六、近似匹配

场景:match query,只能搜索到包含java和spark的document,但是不知道java和spark是不是离的很近
需求1:java spark,靠在一起,中间不能插入任何其他字符
需求2:java spark,要求java和spark两个单词靠的越近,doc的分数越高,排名越靠前
1.短语匹配 match_phrase
GET /forum/article/_search
{
"query": {
"match_phrase": {
"content": "java spark"
}
}
}
2.近似匹配 proximity match
GET /forum/article/_search
{
"query": {
"match_phrase": {
"title": {
"query": "java spark",
"slop":  3
}
}
}
}
slop:最多经过几多少次移动才能与一个document匹配
3.召回率:搜索java spark,总共有100个doc,能返回多少个doc作为结果,就是recall
  精准度:搜索java spark,能不能尽可能让包含java spark,或者是java和spark离的很近的doc,排在最前面,就是precision
  近似匹配的时候,召回率比较低,精准度太高了,此时可以用bool组合match query和match_phrase query一起,来实现召回率和精准度
  例:
GET /forum/article/_search 
{
 "query": {
"bool": {
 "must": [
{
 "match": {
"content": "java spark"
 }
}
 ],
 "should": [
{
 "match_phrase": {
"content": {
 "query": "java spark",
 "slop": 50
}
 }
}
 ]
}
 }
}
4.rescore重计分
优化proximity match的性能,一般就是减少要进行proximity match搜索的document数量。主要思路就是,用match query先过滤出需要的数据,然后再用proximity match来根据term距离提高doc的分数,同时proximity match只针对每个shard的分数排名前n个doc起作用,来重新调整它们的分数,这个过程称之为rescoring,重计分。因为一般用户会分页查询,只会看到前几页的数据,所以不需要对所有结果进行proximity match操作。
例:GET /forum/article/_search 
{
  "query": {
    "match": {
      "content": "java spark"
    }
  },
  "rescore": {
    "window_size": 50,
    "query": {
      "rescore_query": {
        "match_phrase": {
          "content": {
            "query": "java spark",
            "slop": 50
          }
        }
      }
    }
  }
}

七、几种常用搜索

1.前缀搜索
prefix query不计算relevance score,与prefix filter唯一的区别就是,filter会cache bitset,扫描整个倒排索引。
前缀越短,要处理的doc越多,性能越差,尽可能用长前缀搜索。
例:GET my_index/my_type/_search
{
  "query": {
"prefix": {
 "title": {
"value": "C3"
 }
}
  }
}
2.通配符搜索
性能一样差,必须扫描整个倒排索引。
?:任意字符
*:0个或任意多个字符
例:GET my_index/my_type/_search
{
  "query": {
"wildcard": {
 "title": {
"value": "C?K*5"
 }
}
  }
}
3.正则搜索
wildcard和regexp,与prefix原理一致,都会扫描整个索引,性能很差。
.:一个字符
+:前面的正则表达式可以出现一次或多次
例:GET /my_index/my_type/_search 
{
  "query": {
"regexp": {
 "title": "C[0-9].+"
}
  }
}
4.误拼写fuzzy模糊搜索技术
自动将拼写错误的搜索文本,进行纠正,纠正以后去尝试匹配索引中的数据。
fuzziness,你的搜索文本最多可以纠正几个字母去跟你的数据进行匹配,默认如果不设置,就是2。
例1:
GET /my_index/my_type/_search 
{
  "query": {
"fuzzy": {
 "text": {
"value": "surprize",
"fuzziness": 2
 }
}
  }
}
例2:
GET /my_index/my_type/_search 
{
  "query": {
"match": {
 "text": {
"query": "SURPIZE ME",
"fuzziness": "AUTO",
"operator": "and"
 }
}
  }
}

八、搜索推荐

原理跟match_phrase类似,唯一的区别,就是把最后一个term作为前缀去搜索,最后一个前缀始终要去扫描大量的索引,性能可能会很差。
max_expansions:指定prefix最多匹配多少个term,超过这个数量就不继续匹配了,限定性能
例:
GET /my_index/my_type/_search 
{
  "query": {
"match_phrase_prefix": {
 "title": "hello d"
}
  }
}
1.ngram和index-time搜索推荐原理
ngram举例:
ngram length=1,q u i c k
ngram length=2,qu ui ic ck
ngram length=3,qui uic ick
ngram length=4,quic uick
ngram length=5,quick
edge ngram举例:
q
qu
qui
quic
quick
例:使用edge ngram将每个单词都进行进一步的分词切分,用切分后的ngram来实现前缀搜索推荐功能
PUT /my_index
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": { 
"type":     "edge_ngram",
"min_gram": 1,
"max_gram": 20
}
},
"analyzer": {
"autocomplete": {
"type":      "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter" 
]
}
}
}
}
}
PUT /my_index/_mapping/my_type
{
  "properties": {
 "title": {
 "type":     "string",
 "analyzer": "autocomplete",
 "search_analyzer": "standard"
 }
  }
}
GET /my_index/my_type/_search 
{
  "query": {
"match_phrase": {
 "title": "hello w"
}
  }
}
如果用match,只有hello的也会出来,全文检索,只是分数比较低
推荐使用match_phrase,要求每个term都有,而且position刚好靠着1位,符合我们的期望的

九、三种highligh及标签设置

1.plain highlight:即lucene highlight(默认)
2.posting highlight:设置index_options=offsets
性能比plain highlight要高,因为不需要重新对高亮文本进行分词
对磁盘的消耗更少
将文本切割为句子,并且对句子进行高亮,效果更好
例:PUT /blog_website
{
 "mappings": {
"blogs": {
 "properties": {
"title": {
 "type": "text",
 "analyzer": "ik_max_word"
},
"content": {
 "type": "text",
 "analyzer": "ik_max_word",
 "index_options": "offsets"
}
 }
}
 }
}
3.fast vector highlight:设置term_vector=with_positions_offsets
如果field的值特别大,超过了1M,那么可以用fast vector highlight
4.设置高亮html标签,默认是<em>标签
GET /blog_website/blogs/_search 
{
 "query": {
"match": {
 "content": "博客"
}
 },
 "highlight": {
"pre_tags": ["<tag1>"],
"post_tags": ["</tag2>"], 
"fields": {
 "content": {
"type": "plain"
 }
}
 }
}
5.高亮片段fragment的设置
GET /_search
{
    "query" : {
        "match": { "user": "kimchy" }
    },
    "highlight" : {
        "fields" : {
            "content" : {"fragment_size" : 150, "number_of_fragments" : 3, "no_match_size": 150 }
        }
    }
}
fragment_size: Field的值比如有长度是1万,但是不可能在页面上显示这么长,设置要显示出来的fragment文本判断的长度,默认是100
number_of_fragments:可能高亮的fragment文本片段有多个片段,可以指定就显示几个片段

十、搜索模板(待续)
十一、filter执行原理

为每个在倒排索引中搜索到的结果,构建一个bitset,如[0, 0, 0, 1, 0, 1]
遍历每个过滤条件对应的bitset,优先从最稀疏的开始搜索,查找满足所f有ilter条件的document,直到bitset遍历完
caching bitset,跟踪query,在最近256个query中超过一定次数的过滤条件,缓存其bitset。对于小于segment(<1000,或<3%),不缓存bitset。
如果document有新增或修改,那么cached bitset会被自动更新

猜你喜欢

转载自blog.csdn.net/zhou870498/article/details/80503403