Elasticsearch进阶笔记第五篇

280 阅读3分钟

Elasticsearch高手进阶篇(9)

基于boost的细粒度搜索条件权重控制

需求:

  • 搜索标题中包含java的帖子,同时呢,如果标题中包含hadoop或elasticsearch就优先搜索出来,同时呢,如果一个帖子包含java hadoop,一个帖子包含java elasticsearch,包含hadoop的帖子要比elasticsearch优先搜索出来

搜索条件的权重boost

  • boost

    • 可以将某个搜索条件的权重加大,此时当匹配这个搜索条件和匹配另一个搜索条件的document,计算relevance score时,匹配权重更大的搜索条件的document,relevance score会更高,当然也就会优先被返回回来
    • 默认情况下,搜索条件的权重都是一样的,都是1
 GET /forum/article/_search 
 {
   "query": {
     "bool": {
       "must": [
         {
           "match": {
             "title": "blog"
           }
         }
       ],
       "should": [
         {
           "match": {
             "title": {
               "query": "java"
             }
           }
         },
         {
           "match": {
             "title": {
               "query": "hadoop"
             }
           }
         },
         {
           "match": {
             "title": {
               "query": "elasticsearch"
             }
           }
         },
         {
           "match": {
             "title": {
               "query": "spark",
               "boost": 5
             }
           }
         }
       ]
     }
   }
 }
 
 {
   "took": 2,
   "timed_out": false,
   "_shards": {
     "total": 5,
     "successful": 5,
     "failed": 0
   },
   "hits": {
     "total": 5,
     "max_score": 1.7260925,
     "hits": [
       {
         "_index": "waws",
         "_type": "article",
         "_id": "5",
         "_score": 1.7260925,
         "_source": {
           "articleID": "DHJK-B-1395-#Ky5",
           "userID": 3,
           "hidden": false,
           "postDate": "2017-03-01",
           "tag": [
             "elasticsearch"
           ],
           "tag_cnt": 1,
           "view_cnt": 10,
           "title": "this is spark blog"
         }
       },
       {
         "_index": "waws",
         "_type": "article",
         "_id": "4",
         "_score": 1.4930474,
         "_source": {
           "articleID": "QQPX-R-3956-#aD8",
           "userID": 2,
           "hidden": true,
           "postDate": "2017-01-02",
           "tag": [
             "java",
             "elasticsearch"
           ],
           "tag_cnt": 2,
           "view_cnt": 80,
           "title": "this is java, elasticsearch, hadoop blog"
         }
       },
       {
         "_index": "waws",
         "_type": "article",
         "_id": "1",
         "_score": 0.80226827,
         "_source": {
           "articleID": "XHDK-A-1293-#fJ3",
           "userID": 1,
           "hidden": false,
           "postDate": "2017-01-01",
           "tag": [
             "java",
             "hadoop"
           ],
           "tag_cnt": 2,
           "view_cnt": 30,
           "title": "this is java and elasticsearch blog"
         }
       },
       {
         "_index": "waws",
         "_type": "article",
         "_id": "3",
         "_score": 0.5753642,
         "_source": {
           "articleID": "JODL-X-1937-#pV7",
           "userID": 2,
           "hidden": false,
           "postDate": "2017-01-01",
           "tag": [
             "hadoop"
           ],
           "tag_cnt": 1,
           "view_cnt": 100,
           "title": "this is elasticsearch blog"
         }
       },
       {
         "_index": "waws",
         "_type": "article",
         "_id": "2",
         "_score": 0.3971361,
         "_source": {
           "articleID": "KDKE-B-9947-#kL5",
           "userID": 1,
           "hidden": false,
           "postDate": "2017-01-02",
           "tag": [
             "java"
           ],
           "tag_cnt": 1,
           "view_cnt": 50,
           "title": "this is java blog"
         }
       }
     ]
   }
 }

Elasticsearch高手进阶篇(10)

深度探秘搜索技术_多shard场景下relevance score不准确问题大揭秘

根本原因:多shard在本地进行计算

1、多shard场景下relevance score不准确问题大揭秘

如果你的一个index有多个shard的话,可能搜索结果会不准确

  • 个人理解:

    • 我们的index可能包含很多个shard,所以我们的一个shard上只是完整的document的一部分,我们在使用TF/IDF进行相关性分数计算的时候,shard只是一部分的document,默认,就在shard local本地计算IDF,我们假设我们有两个shard,P0和P1,java这个词在P0中比较多,但是在P1中比较少,这样就会导致我们在P0中原本相关度很高的结果,因为在同一个shard中的java过多,进而导致IDF下降,最后排名靠后,我们最终获取到的数据的排序就不是我们想要的数据

image.png

2、如何解决该问题?

  • 生产环境下,数据量大,尽可能实现均匀分配

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

    • 如果说只有一个shard,那么当然,所有的document都在这个shard里面,就没有这个问题了
  • 测试环境下,搜索附带search_type=dfs_query_then_fetch参数,会将local IDF取出来计算global IDF

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