参考文章:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/scoring-theory.html
一个被认定为和短语 quick brown fox 匹配的文档,必须满足以下这些要求:
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": "quick brown fox"
}
}
}
or
"match": {
"title": {
"query": "quick brown fox",
"type": "phrase"
}
}
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": {
"query": "quick fox",
"slop": 1
}
}
}
}
slop决定了短语匹配中词的间隔和顺序
搜索 fox quick
那么slop至为2才能搜索出 quick fox的文本
Pos 1 Pos 2 Pos 3
-----------------------------------------------
Doc: quick brown fox
-----------------------------------------------
Query: fox quick
Slop 1: fox|quick ↵//这一步fox和quick位置一样
Slop 2: quick ↳ fox
Slop 3: quick ↳ fox
PUT /my_index/groups/1
{
"names": [ "John Abraham", "Lincoln Smith"]
}
短语查询
GET /my_index/groups/_search
{
"query": {
"match_phrase": {
"names": "Abraham Lincoln"
}
}
}
此时的position如下:
那么这里就会出现错误的搜索结果,该条记录将被命中
解决办法
"properties": {
"names": {
"type": "string",
"position_increment_gap": 100
}
}
}
此时的position
此时slop要为100才能被命中
当你给了slop一个交大的值,那么词越近的时候,分数越高
POST /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": {
"query": "quick dog",
"slop": 50
}
}
}
}
{
"hits": [
{
"_id": "3",
"_score": 0.75,
"_source": {
"title": "The quick brown fox jumps over the quick dog"
}
},
{
"_id": "2",
"_score": 0.28347334,
"_source": {
"title": "The quick brown fox jumps over the lazy dog"
}
}
]
}
GET /my_index/my_type/_search
{
"query": {
"bool": {
"must": {
"match": {
"title": {
"query": "quick brown fox",
"minimum_should_match": "30%"
}
}
},
"should": {
"match_phrase": {
"title": {
"query": "quick brown fox",
"slop": 50
}
}
}
}
}
}
由于短语匹配,所有的词必须出现,且他们的位置也有相关要求,所以为了提高范围,通过bool操作来实现。
在先前的章节中 ,我们讨论了而使用邻近查询来调整相关度,而不是使用它将文档从结果列表中添加或者排除。 一个查询可能会匹配成千上万的结果,但我们的用户很可能只对结果的前几页感兴趣。
一个简单的 match 查询已经通过排序把包含所有含有搜索词条的文档放在结果列表的前面了。事实上,我们只想对这些 顶部文档 重新排序,来给同时匹配了短语查询的文档一个额外的相关度升级。
search API 通过 重新评分 明确支持该功能。重新评分阶段支持一个代价更高的评分算法–比如 phrase 查询–只是为了从每个分片中获得前 K 个结果。 然后会根据它们的最新评分 重新排序。
该请求如下所示:
GET /my_index/my_type/_search
{
"query": {
//match 查询决定哪些文档将包含在最终结果集中,并通过 TF/IDF 排序。
"match": {
"title": {
"query": "quick brown fox",
"minimum_should_match": "30%"
}
}
},
"rescore": {
//window_size 是每一分片进行重新评分的顶部文档数量。
"window_size": 50,
"query": {
// 目前唯一支持的重新打分算法就是另一个查询,但是以后会有计划增加更多的算法。
"rescore_query": {
"match_phrase": {
"title": {
"query": "quick brown fox",
"slop": 50
}
}
}
}
}
}
[“sue”, “ate”, “the”, “alligator”]
[“sue ate”, “ate the”, “the alligator”]
[“sue ate the”, “ate the alligator”]
DELETE /my_index
PUT /my_index
{
"settings": {
"number_of_shards": 1,
"analysis": {
"filter": {
"my_shingle_filter": {
"type": "shingle",
"min_shingle_size": 2,
"max_shingle_size": 2,
"output_unigrams": false
}
},
"analyzer": {
"my_shingle_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"my_shingle_filter"
]
}
}
}
}
}
多字段
PUT /my_index/_mapping/my_type
{
"my_type": {
"properties": {
"title": {
"type": "string",
"fields": {
"shingles": {
"type": "string",
"analyzer": "my_shingle_analyzer"
}
}
}
}
}
}
GET /my_index/my_type/_search
{
"query": {
"bool": {
"must": {
"match": {
"title": "the hungry alligator ate sue"
}
},
"should": {
"match": {
"title.shingles": "the hungry alligator ate sue"
}
}
}
}
}
性能
shingles 不仅比短语查询更灵活, 而且性能也更好。 shingles 查询跟一个简单的 match 查询一样高效,而不用每次搜索花费短语查询的代价。只是在索引期间因为更多词项需要被索引会付出一些小的代价, 这也意味着有 shingles 的字段会占用更多的磁盘空间。 然而,大多数应用写入一次而读取多次,所以在索引期间优化我们的查询速度是有意义的。
select * from t1 where t1.a like ‘%tom%’
GET /my_index/address/_search
{
"query": {
"prefix": {
"postcode": "W1"
}
}
}
为了支持前缀匹配,查询会做以下事情:
当字段中词的集合很小时,可以放心使用,但是它的伸缩性并不好,会对我们的集群带来很多压力。可以使用较长的前缀来限制这种影响,减少需要访问的量。
? 匹配任意字符, * 匹配 0 或多个字符
GET /my_index/address/_search
{
"query": {
"wildcard": {
"postcode": "W?F*HW"
}
}
}
这个正则表达式要求词必须以 W 开头,紧跟 0 至 9 之间的任何一个数字,然后接一或多个其他字符。
GET /my_index/address/_search
{
"query": {
"regexp": {
"postcode": "W[0-9].+"
}
}
}
注意:wildcard 和 regexp 查询的工作方式与 prefix 查询完全一样,性能问题
这些部分匹配都是词查询,都是基于词项查询的。
短语前缀匹配
{
"match_phrase_prefix" : {
"brand" : {
"query": "walker johnnie bl",
"slop": 10
}
}
}
//explain
"johnnie walker bl*"
参数 max_expansions 控制着可以与前缀匹配的词的数量,它会先查找第一个与前缀 bl 匹配的词,然后依次查找搜集与之匹配的词(按字母顺序),直到没有更多可匹配的词或当数量超过 max_expansions 时结束。
不要忘记,当用户每多输入一个字符时,这个查询又会执行一遍,所以查询需要快,如果第一个结果集不是用户想要的,他们会继续输入直到能搜出满意的结果为止。
{
"match_phrase_prefix" : {
"brand" : {
"query": "johnnie walker bl",
"max_expansions": 50
}
}
}
quick
索引
token过滤器
{
"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
{
"settings": {
"number_of_shards": 1,
"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
{
"my_type": {
"properties": {
"name": {
"type": "string",
"analyzer": "autocomplete"
}
}
}
}
查询
GET /my_index/my_type/_search
{
"query": {
"match": {
"name": {
"query": "brown fo",
"analyzer": "standard"
}
}
}
}
复合词的使用
PUT /my_index
{
"settings": {
"analysis": {
"filter": {
"trigrams_filter": {
"type": "ngram",
"min_gram": 3,
"max_gram": 3
}
},
"analyzer": {
"trigrams": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"trigrams_filter"
]
}
}
}
},
"mappings": {
"my_type": {
"properties": {
"text": {
"type": "string",
"analyzer": "trigrams"
}
}
}
}
}
GET /my_index/my_type/_search
{
"query": {
"match": {
"text": {
"query": "Gesundheit",
"minimum_should_match": "80%"
}
}
}
}
参考文章:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/scoring-theory.html