一、多shard场景下relevance
score不准确问题
    1、问题描述:
           多个shard下,如果每个shard包含指定搜索条件的document数量不均匀的情况下,会导致在某个shard上document数量少的时候,计算该指定搜索条件的document的相关性评分要虚高。导致该document比实际真正想要返回的document的评分要高。
    2、解决
        (1)生产环境下,数据量大,尽可能实现均匀分配

数据量很大的话,其实一般情况下,在概率学的背景下,es都是在多个shard中均匀路由数据的,路由的时候根据_id,负载均衡
比如说有10个document,title都包含java,一共有5个shard,那么在概率学的背景下,如果负载均衡的话,其实每个shard都应该有2个doc,title包含java
如果说数据分布均匀的话,其实就没有刚才说的那个问题了

(2)测试环境下,将索引的primary
shard设置为1个,number_of_shards=1,index settings

如果说只有一个shard,那么当然,所有的document都在这个shard里面,就没有这个问题了

(3)测试环境下,搜索附带search_type=dfs_query_then_fetch参数,会将local
IDF取出来计算global IDF

计算一个doc的相关度分数的时候,就会将所有shard对的local
IDF计算一下,获取出来,在本地进行global
IDF分数的计算,会将所有shard的doc作为上下文来进行计算,也能确保准确性。但是production生产环境下,不推荐这个参数,因为性能很差。

二、多字段搜索相关性评分计算(best
fields策略,most_field策略)

1、为帖子数据增加content字段

POST
/forum/article/_bulk
{ "update": { "_id": "1"}
}
{ "doc" : {"content" : "i like to
write best elasticsearch article"} }
{ "update": { "_id": "2"}
}
{ "doc" : {"content" : "i think java
is the best programming language"} }
{ "update": { "_id": "3"}
}
{ "doc" : {"content" : "i am only an
elasticsearch beginner"} }
{ "update": { "_id": "4"}
}
{ "doc" : {"content" : "elasticsearch
and hadoop are all very good solution, i am a beginner"}
}
{ "update": { "_id": "5"}
}
{ "doc" : {"content" : "spark is best
big data solution based on scala ,an programming language similar to java"}
}

2、搜索title或content中包含java或solution的帖子

下面这个就是multi-field搜索,多字段搜索

GET
/forum/article/_search
{
    "query":
{
        "bool":
{
            "should":
[
                {
"match": { "title": "java solution" }},
                {
"match": { "content":  "java solution"
}}
            ]
        }
    }
}

3、结果分析

期望的是doc5,结果是doc2,doc4排在了前面

计算每个document的relevance
score:每个query的分数,乘以matched query数量,除以总query数量

算一下doc4的分数

{ "match": { "title": "java solution"
}},针对doc4,是有一个分数的
{ "match": {
"content":  "java solution"
}},针对doc4,也是有一个分数的

所以是两个分数加起来,比如说,1.1 + 1.2 =
2.3
matched query数量 =
2
总query数量 =
2

2.3 * 2 / 2 =
2.3

算一下doc5的分数

{ "match": { "title": "java solution"
}},针对doc5,是没有分数的
{ "match": {
"content":  "java solution"
}},针对doc5,是有一个分数的

所以说,只有一个query是有分数的,比如2.3
matched query数量 =
1
总query数量 =
2

2.3 * 1 / 2 =
1.15

doc5的分数 = 1.15 < doc4的分数 =
2.3

4、best
fields策略,dis_max

best
fields策略,就是说,搜索到的结果,应该是某一个field中匹配到了尽可能多的关键词,被排在前面;而不是尽可能多的field匹配到了少数的关键词,排在了前面

dis_max语法,直接取多个query中,分数最高的那一个query的分数即可

{ "match": { "title": "java solution"
}},针对doc4,是有一个分数的,1.1
{ "match": {
"content":  "java solution"
}},针对doc4,也是有一个分数的,1.2
取最大分数,1.2

{ "match": { "title": "java solution"
}},针对doc5,是没有分数的
{ "match": {
"content":  "java solution"
}},针对doc5,是有一个分数的,2.3
取最大分数,2.3

然后doc4的分数 = 1.2 < doc5的分数 =
2.3,所以doc5就可以排在更前面的地方,符合我们的需要

GET
/forum/article/_search
{
    "query":
{
        "dis_max": {
            "queries":
[
                {
"match": { "title": "java solution" }},
                {
"match": { "content":  "java solution"
}}
            ]
        }
    }
}
            5、dis_max的优化、改进
                    dis_max只取某一个query最大的分数,完全不考虑其他query的分数。这样存在返回的document不是预期的情况
tie_breaker参数的意义,在于说,将其他query的分数,乘以tie_breaker,然后综合与最高分数的那个query的分数,综合在一起进行计算
除了取最高分以外,还会考虑其他的query的分数
 tie_breaker的值,在0~1之间,是个小数,就ok

GET
/forum/article/_search
{
    "query":
{
        "dis_max":
{
            "queries":
[
                {
"match": { "title": "java beginner" }},
                {
"match": { "body":  "java beginner"
}}
            ],
            "tie_breaker":
0.3
        }
    }
}

6.基于multi_match语法实现dis_max+tie_breaker

GET
/forum/article/_search
{
  "query":
{
    "multi_match": {
       "query":                "java
solution",
        "type":                 "best_fields",
        "fields":               [
"title^2", "content" ],   //title^2表示
boost设置为2
        "tie_breaker":          0.3,
        "minimum_should_match":
"50%"
    }
  }
}

(1)minimum_should_match,主要是用来干嘛的?
去长尾,long
tail
长尾,比如你搜索5个关键词,但是很多结果是只匹配1个关键词的,其实跟你想要的结果相差甚远,这些结果就是长尾
minimum_should_match,控制搜索结果的精准度,只有匹配一定数量的关键词的数据,才能返回
(2)title^2表示
boost设置为2

GET
/forum/article/_search
{
  "query":
{
    "dis_max":
{
      "queries":  [
        {
          "match":
{
            "title":
{
              "query":
"java beginner",
              "minimum_should_match":
"50%",
          "boost":
2
            }
          }
        },
        {
          "match":
{
            "content":
{
              "query":
"java beginner",
              "minimum_should_match":
"50%"
            }
          }
        }
      ],
      "tie_breaker":
0.3
    }
  }
}

7、most_fields策略

best-fields策略,主要是说将某一个field匹配尽可能多的关键词的doc优先返回回来
most-fields策略,主要是说尽可能返回更多field匹配到某个关键词的doc,优先返回回来

不同字段使用不同的分词器,对应不同的查询行为。
POST
/forum/_mapping/article
{
  "properties":
{
      "sub_title":
{
          "type":     "string",
          "analyzer":
"english",            //
sub_title 使用english分词器
          "fields":
{
              "std":   {
                  "type":     "string",
                  "analyzer":
"standard"     //sub_title字段的子字段std使用standard分词器
              }
          }
      }
  }
}
sub_title字段english分词器:
    会将单词还原为其最基本的形态,stemmer
learning -->
learn
learned -->
learn
courses -->
course
                 subtitle.std子字段standard分词器: 保留当前字段值得原始值得时态信息等

                POST
/forum/article/_bulk
{ "update": { "_id": "1"}
}
{ "doc" : {"sub_title" : "learning
more courses"} }
{ "update": { "_id": "2"}
}
{ "doc" : {"sub_title" : "learned a
lot of course"} }
{ "update": { "_id": "3"}
}
{ "doc" : {"sub_title" : "we have a
lot of fun"} }
{ "update": { "_id": "4"}
}
{ "doc" : {"sub_title" : "both of them
are good"} }
{ "update": { "_id": "5"}
}
{ "doc" : {"sub_title" : "haha, hello
world"} }

GET
/forum/article/_search
{
  "query":
{
    "match":
{
      "sub_title":
"learning courses"
    }
  }

}

                    基于multi_match的most_fields
                GET
/forum/article/_search
{
   "query":
{
        "multi_match":
{
            "query":  "learning
courses",
            "type":   "most_fields",
            "fields":
[ "sub_title", "sub_title.std"
]
        }
    }
}
            8、best_fields与most_fields:
(1)best_fields,是对多个field进行搜索,挑选某个field匹配度最高的那个分数,同时在多个query最高分相同的情况下,在一定程度上考虑其他query的分数。简单来说,你对多个field进行搜索,就想搜索到某一个field尽可能包含更多关键字的数据

优点:通过best_fields策略,以及综合考虑其他field,还有minimum_should_match支持,可以尽可能精准地将匹配的结果推送到最前面
缺点:除了那些精准匹配的结果,其他差不多大的结果,排序结果不是太均匀,没有什么区分度了

实际的例子:百度之类的搜索引擎,最匹配的到最前面,但是其他的就没什么区分度了

(2)most_fields,综合多个field一起进行搜索,尽可能多地让所有field的query参与到总分数的计算中来,此时就会是个大杂烩,出现类似best_fields案例最开始的那个结果,结果不一定精准,某一个document的一个field包含更多的关键字,但是因为其他document有更多field匹配到了,所以排在了前面;所以需要建立类似sub_title.std这样的field,尽可能让某一个field精准匹配query
string,贡献更高的分数,将更精准匹配的数据排到前面

优点:将尽可能匹配更多field的结果推送到最前面,整个排序结果是比较均匀的
缺点:可能那些精准匹配的结果,无法推送到最前面

实际的例子:wiki,明显的most_fields策略,搜索结果比较均匀,但是的确要翻好几页才能找到最匹配的结果







Elasticsearch学习笔记(十四)relevance score相关性评分的计算(1)的更多相关文章

  1. elasticsearch relevance score相关性评分的计算

    一.多shard场景下relevance score不准确问题 1.问题描述: 多个shard下,如果每个shard包含指定搜索条件的document数量不均匀的情况下,会导致在某个shard上doc ...

  2. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  3. (C/C++学习笔记) 十四. 动态分配

    十四. 动态分配 ● C语言实现动态数组 C语言实现动态数组,克服静态数组大小固定的缺陷 C语言中,数组长度必须在创建数组时指定,并且只能是一个常数,不能是变量.一旦定义了一个数组,系统将为它分配一个 ...

  4. Swift学习笔记十四:构造(Initialization)

         类和结构体在实例创建时,必须为全部存储型属性设置合适的初始值. 存储型属性的值不能处于一个未知的状态.     你能够在构造器中为存储型属性赋初值,也能够在定义属性时为其设置默认值.下面章节 ...

  5. SharpGL学习笔记(十四) 材质:十二个材质球

    材质颜色 OpenGL用材料对光的红.绿.蓝三原色的反射率来近似定义材料的颜色.象光源一样,材料颜色也分成环境.漫反射和镜面反射成分,它们决定了材料对环境光.漫反射光和镜面反射光的反射程度.在进行光照 ...

  6. 【转】angular学习笔记(十四)-$watch(1)

    本篇主要介绍$watch的基本概念: $watch是所有控制器的$scope中内置的方法: $scope.$watch(watchObj,watchCallback,ifDeep) watchObj: ...

  7. Elasticsearch学习笔记(四)ElasticSearch分布式机制

    一.Elasticsearch对复杂分布式机制透明的隐藏特性 1.分片机制: (1)index包含多个shard,每个shard都是一个最小工作单元,承载部分数据,lucene实例,完整的建立索引和处 ...

  8. angular学习笔记(十四)-$watch(1)

    本篇主要介绍$watch的基本概念: $watch是所有控制器的$scope中内置的方法: $scope.$watch(watchObj,watchCallback,ifDeep) watchObj: ...

  9. Java学习笔记十四:如何定义Java中的类以及使用对象的属性

    如何定义Java中的类以及使用对象的属性 一:类的重要性: 所有Java程序都以类class为组织单元: 二:什么是类: 类是模子,确定对象将会拥有的特征(属性)和行为(方法): 三:类的组成: 属性 ...

随机推荐

  1. JVM--02

    Java虚拟机内存管理: 共享: 方法区:存储运行时常量池.已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据 java堆:存储对象实例 线程独占区: 虚拟机栈:存放方法运行时所需的 ...

  2. Python--可迭代对象,迭代器,生成器

    记得在刚开始学Python的时候,看到可迭代对象(iterable).迭代器(iterator)和生成器(generator)这三个名词时,完全懵逼了,根本就不知道是啥意识.现在以自己的理解来详解下这 ...

  3. 进入django

    web应用,c/s,b/s架构 c/s: 客户端 服务端 b/s: 浏览器 服务器 HTTP协议: 超文本传输协议 四大特性: 1.基于TCP/IP作用在应用层之上的协议 2.基于请求响应 3.无状态 ...

  4. Nikto and whatweb

    root@kali:~# nikto -host www.baidu.com- Nikto v2.1.6------------------------------------------------ ...

  5. sass基础—继承及占位符

    /*继承:@extend ,继承多个类时使用逗号隔开*/.alert{ color: #f00;}.info{ width: 100px;} .text-danger{ background-colo ...

  6. 快速部署docker

    前言:docker就不用说了,好东西啊.更好的利用服务器的资源,各个服务是相互隔离的,文件的存放更加规律,也好清理空间及数据备份 docker安装-----社区版ce(免费的,另一版本收钱的) 系统: ...

  7. Actor消息发送及等待结果关键字

    class Task extends Actor{ override def act(): Unit = { while(true){ receive({ case SmTask(file) => ...

  8. Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  9. 如何手写Ajax实现异步刷新

    所谓的异步刷新,就是不刷新整个网页进行更新数据. 只有通过js才能实现Ajax,进而实行异步刷新 表单提交数据和Ajax提交数据的区别:表单提交是提交的整个页面中的数据,提交数据之后会抛弃之前的页面( ...

  10. Git基本操作指令

    Git是世界上目前最先进的分布式版本控制系统. 工作原理图: Workspace工作区,Index暂存区,Repository本地仓库区,Remote远程仓库. SVN与Git的最主要的区别? SVN ...