全文搜索
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
实际上!完全没有必要使用,只要有足够的数据就能保证词频是均匀分布的。
网友评论