二十一、ElasticsSearch中使用terms、range、should、minimum_should_match、operator、dis_max、tie_breaker的使用

1、terms 相當于sql中的in,多值搜索

GET /forum/article/_search

{

"query": {

"constant_score": {

  "filter": {

    "bool": {

      "must": [

        {

          "term": {

            "tag_cnt": 1

          }

        },

        {

          "terms": {

            "tag": ["java",”c++”]

          }

        }

      ]

    }

  }

}

}

}

2、搜索瀏覽量在30~60之間的帖子

GET /forum/article/_search

{

"query": {

"constant_score": {

  "filter": {

    "range": {

      "view_cnt": {

        "gt": 30,

        "lt": 60

      }

    }

  }

}

}

}

gte lte包含

3、搜索標題中包含java或elasticsearch的

GET /forum/article/_search

{

"query": {

"match": {

  "title": "java elasticsearch"

}

}

}

如果想同時滿足,可以加operator

GET /forum/article/_search

{

"query": {

"match": {

  "title": {

    "query": "java elasticsearch",

    "operator": "and"

  }

}

}

}

在es內部,會轉換成下面的去執行

{

"bool": {

"must": [

  { "term": { "title": "java" }},

  { "term": { "title": "elasticsearch"   }}

]

}

}

使用minimum_should_match,必須至少匹配其中的多少個關鍵字,才能作為結果返回,可以用數字也可以使用百分比

GET /forum/article/_search

{

"query": {

"match": {

  "title": {

    "query": "java elasticsearch hadoop spark,",

    "minimum_should_match": “75”%

  }

}

}

}

也可以使用下面的should寫法,當然,上面的語法,在es內部都會處理成下面的去查詢

GET /forum/article/_search

{

"query": {

"bool": {

  "should": [

    {"match": {

      "title": "java"

    }},

    {"match": {

      "title": "elasticsearch"

    }},

    {

      "match": {

        "title": "hadoop"

      }

    },

    {

      "match": {

        "title": "spark"

      }

    }

  ],

"minimum_should_match":3

}

}

}

4、boost的搜索條件權重控制

指定查詢的內容中,什么排在最前面,默認是一樣的,數值是你所查詢中的條件個數+1,這樣才會最優在前

GET /forum/article/_search

{

"query": {

"bool": {

  "should": [

    {"match": {

      "title": {

        "query":"java"

      }

    }},

    {"match": {

      "title": {"query":"elasticsearch"}

    }},

    {

      "match": {

        "title": {"query":"hadoop"}

      }

    },

    {

      "match": {

        "title":{"query":"spark",

        "boost":5}

      }

    }

  ]

}

}

}

5、多shard場景下relevance score不準確問題大揭秘

如果你的一個index有多個shard的話,可能搜索結果會不準確

圖片1.png

解決:

(1)生產環境下,數據量大,盡可能實現均勻分配

(2)測試環境下,將索引的primary shard設置為1個,number_of_shards=1

(3)測試環境下,搜索附帶search_type=dfs_query_then_fetch參數,會將local IDF取出來計算從新計算,但是生產環境下,不推薦這個參數,因為性能很差。

GET /forum/article/_search?search_type=dfs_query_then_fetch

6、dis_max實現best fields策略進行多字段搜索

(1)****搜索title或content中包含java或solution的帖子
GET /forum/article/_search
{
"query": {
"bool": {
"should": [
{"match": { "title": "java solution"}},
{"match": {
"content": "java solution"
}}
]
}
}
}

{
"_index": "forum",
"_type": "article",
"_id": "4",
"_score": 0.7120095,
"_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",
"content": "elasticsearch and hadoop are all very good solution, i am a beginner"
}
},
{
"_index": "forum",
"_type": "article",
"_id": "5",
"_score": 0.56008905,
"_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",
"content": "spark is best big data solution based on scala ,an programming language similar to java"
}
},

(2)結果分析

期望的是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

(3)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" }}

        ]

    }

}

}

(4)、tie_breaker參數優化dis_max搜索效果

dis_max只取某一個query最大的分數,完全不考慮其他query的分數,可能會導致排序不一對,可以使用tie_breaker將其他query的分數也考慮進去

GET /forum/article/_search

{

"query": {

"dis_max": {

  "queries": [{"match": {

    "title": "java solution"

  }},{"match": {

    "content": "java solution"

  }}],"tie_breaker": 0.3

}

}

}

7、multi_match語法實現dis_max+tie_breaker

GET /forum/article/_search

{

"query": {

"multi_match": {

  "query": "java solution",

  "fields": ["title^2","content"],

  "type": "best_fields",

  "tie_breaker": 0.3,

  "minimum_should_match":"70%"

}

}

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容