Full Text Search

全文搜索

1、相关性
评价查询与其结果间的相关程度,并根据这种相关程度对结果排名。
计算方式:TF/IDF、地理位置邻近、模糊相似、或者其他某些算法。
2、分析
将文本转换为有区别的、规范化的token的一个过程。
创建倒排索引以及查询倒排索引

基于词项与基于全文

1、基于词项的查询
term或fuzzy这样的底层查询不需要分析阶段,它们对单个词项进行操作。
只需要在倒排索引中查找准确词项。
2、基于全文的查询
match或query_string这样的查询是高层查询,它们了解字段映射的信息:
-如果查询date或integer字段,它们会将查询字符串分别作为date或integer对待。
-如果查询not_analyzed的精确值字符串字段,它们会将整个查询字符串作为单个词项对待。
-如果查询analyzed的全文字段,它们会先将查询字符串传递到一个合适的分析器,然后生成一个供查询的词项列表。
一旦组成了词项列表,这个查询会对每个词项逐一执行底层的查询。

匹配查询

match是个核心查询、高级全文查询,既能处理全文字段,又能处理精确字段。
它是首选的查询方式
单个词查询

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}

es执行上面这个match查询的步骤是:
1、检查字段类型。
title字段是一个string类型的全文字段,意味着查询字符串本身也应该被分析。
2、分析查询字符串。
传入标准分析中,输出的结果是单个项quick。因为是一个单词项,所以match查询执行的单个底层term查询
3、查询匹配文档
4、为每个文档评分

多词查询

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}

与单词项查询类似,只不过term会被执行多次(多个term包入一个bool中)
多词查询默认情况下,只要匹配一个词就会被匹配(or)

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": {      (1)
                "query":    "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}

使用operator可以修改成and,多个词都被匹配,文档才会被匹配
还可以使用"minimum_should_match": "75%"75%的词项被匹配,文档就会被匹配
但是假如只有三个词项,75%会被自动阶段成66.6%

组合查询

在组合过滤器中,使用bool进行组合,在查询中bool也有类似的功能,只有一个重要的区别。
过滤器是非黑即白的,然而查询会计算文档的相关程度。

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}

上述查询must和must_not与bool过滤器的工作方式非常相似。
区别在于两个should语句:不必包含,但是包含了就更相关了
bool查询会为每个文档计算相关度评分_score,再将所有匹配的must和should语句的分数_score求和,最后除以must和should语句的总数。
must_not不影响评分,只是将不相关的文档排除。
默认情况下没有should语句是必须匹配的,但是当没有must语句的时候。至少有一个should语句必须匹配
类似控制match查询的精度一样,minimum_should_match也可以控制should语句的精度,可以是数字,也可以是百分比

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2
    }
  }
}

查询语句提升权重

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "content": { 
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [ 
                { "match": { "content": "Elasticsearch" }},
                { "match": { "content": "Lucene"        }}
            ]
        }
    }
}

这个查询中content字段必须包含full/text/search,如果包含 Elasticsearch/Lucene会获得更高的评分。
我们想要Elasticsearch/Lucene的权重有些变化,可以使用boost(默认值是1,取值范围>0),boost的提升或者降低不是线性的。有一个归一化的过程

GET /_search
{
    "query": {
        "bool": {
            "must": {
                "match": {  
                    "content": {
                        "query":    "full text search",
                        "operator": "and"
                    }
                }
            },
            "should": [
                { "match": {
                    "content": {
                        "query": "Elasticsearch",
                        "boost": 3 
                    }
                }},
                { "match": {
                    "content": {
                        "query": "Lucene",
                        "boost": 2 
                    }
                }}
            ]
        }
    }
}

控制分析

可以为字段指定分析器,也可以使用type/index/node的默认配置
可以使用analyze API来分析单词

GET /my_index/_analyze
{
  "field": "my_type.title",   (1)
  "text": "Foxes"
}

GET /my_index/_analyze
{
  "field": "my_type.english_title",   (2)
  "text": "Foxes"
}

1使用默认的standard标准分析器,返回词项foxes
2使用english英语分析器,返回词项fox
意味着使用term查询精确项fox时,english_title字段会匹配,但title字段不会
可以使用validate-query API来查看高层查询(例如match)的分析行为

GET /my_index/my_type/_validate/query?explain
{
    "query": {
        "bool": {
            "should": [
                { "match": { "title":         "Foxes"}},
                { "match": { "english_title": "Foxes"}}
            ]
        }
    }
}

返回语句的explanation结果:

(title:foxes english_title:fox)

默认分析器

按照层级顺序查找分析器,直到找到能够使用的分析器。
索引时的顺序如下
1、字段映射里定义的analyzer
2、索引设置中名为default的分析器,默认为standard
3、standard标准分析器
查询时的顺序如下:
1、查询自己定义的analyzer
2、字段映射里定义的analyzer
3、索引设置中名为default的分析器,默认为standard
4、standard标准分析器
索引时和搜索时使用不同的分析器是合理,例如为同义词建索引,但在搜索时我们不需要搜索所有同义词。
为了区分,es支持一个可选的search_analyzer映射,以及一个等价的default_search映射
搜索时,完整顺序如下:
1、查询自己定义的analyzer
2、字段映射里定义的search_analyzer
3、字段映射里定义的analyzer
4、索引设置中名为default_search的分析器,默认为standard
5、索引设置中名为default的分析器,默认为standard
6、standard标准分析器

被破坏的相关度!!!

用户索引了一些文档,运行一个简单的查询,然后发现明显低相关度的结果出现在高相关度结果之上。
由于相似度算法TF/IDF,词频/逆向文档频率
词频是某个词在“当前被查询文档”里面某个字段中出现的频率
逆向文档频率是将某个词在索引内“所有文档”出现的百分数
需要注意的是,es不会计算索引内所有文档的IDF,只会计算分片的本地IDF。
数据较少时,不同分片的IDF差异较大,就会导致相关度被破坏
可以在搜索请求后添加?search_type=dfs_query_then_fetch,dfs 是指 分布式频率搜索(Distributed Frequency Search)分别获得每个分片本地的IDF,然后根据结果再计算全局IDF
实际上!完全没有必要使用,只要有足够的数据就能保证词频是均匀分布的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容