一、match
- 在執行match查詢時,默認情況下,字段值必須匹配任意一個詞條,比如文檔的eventname字段匹配任意一個分詞,azure、aws和cloud時,該文檔就匹配
POST /_search -d
{
"from":10,
"size":5,
"query":{
"match":{
"eventname":"azure aws cloud"
}
}
}
- 匹配分詞的數量是由匹配參數控制的,match查詢常用的參數:
- operator:用來控制match查詢匹配詞條的邏輯條件,默認值是or,如果設置為and,表示查詢滿足所有條件;
- minimum_should_match:當operator參數設置為or時,該參數用來控制應該匹配的分詞的最少數量;Elastic控制查詢精準度-minimum_should_match
POST /search -d{
"from":10,
"size":5,
"query":{
"match":{
"eventname":{
"query":"azure aws cloud security",
"operator":"or",
"minimum_should_match":2
}
}
}
}
POST /search -d{
"from":10,
"size":5,
"query":{
"match":{
"eventname":{
"query":"azure aws cloud security",
"operator":"adn"
}
}
}
}
- 底層實現的轉換 將multi-query 轉換為 bool+ must/should + term
3.1、or
GET /forum/article/_search
{
"query": {
"match": {
"title": "java elasticsearch"
}
}
}
相當于:bool should term
{
"bool": {
"should": [
{ "term": { "title": "java" }},
{ "term": { "title": "elasticsearch" }}
]
}
}
3.2、and
如果title字段是analyzed則進行full text全文搜索,則返回title字段包含java 或者elasticsearch 或者兩個都包含的document
如果是not_analyzed則進行exact value(相當于temr query),則只返回包含java elasticsearch的document
GET /forum/article/_search
{
"query": {
"match": {
"title": {
"query": "java elasticsearch",
"operator": "and" //full text 中 返回都包含“java”和"elasticsearch“的document
}
}
}
}
相當于:bool must term
{
"bool": {
"must": [
{ "term": { "title": "java" }},
{ "term": { "title": "elasticsearch" }}
]
}
}
3.3、minimum_should_match
GET /forum/article/_search
{
"query": {
"match": {
"title": {
"query": "java elasticsearch spark hadoop",
"minimum_should_match": "75%" // full text中返回,包含指定條件的75%的document
}
}
}
}
相當于:bool should term minimum_should_match
{
"bool": {
"should": [
{ "term": { "title": "java" }},
{ "term": { "title": "elasticsearch" }},
{ "term": { "title": "hadoop" }},
{ "term": { "title": "spark" }}
],
"minimum_should_match": 3
}
}
補充知識點:must和should對分數有影響;must是必須條件,之后should匹配的越多則分數越高
更多參考:布爾匹配查詢
二、短語匹配查詢(match_phrase)
Elasticsearch - 短語匹配(match_phrase)以及slop參數
在執行短語匹配查詢時,ElasticSearch引擎首先分析(analyze)查詢字符串,從分析后的文本中構建短語查詢:
- 必須匹配短語中的所有分詞
- 保證各個分詞的相對位置不變
POST /_search -d
{
"from":1,
"size":100,
"fields":[ "eventname"],
"query":{
"match_phrase":{
"eventname":"Open Source"
}
}
}
"this is an Open Souce xxx" 匹配
“Open this Source code xxx" 不匹配
短語匹配使用slop參數來引入一些靈活性;slop參數告訴match_phrase查詢詞條能夠相隔多遠時仍然將文檔視為匹配;其中移動可以是反向的,比如這樣的場景:Open 左移,Source 又移
GET /my_index/my_type/_search
{
"query": {
"match_phrase": {
"title": {
"query": "Open Source",
"slop": 2
}
}
}
}
三、 boost條件權重控制
默認情況下,搜索條件的權重都是一樣的,都是1;boost控制搜索條件的權重,可以將某個搜索條件的權重加大,此時當匹配這個搜索條件和匹配另一個搜索條件的document,計算relevance score時,匹配權重更大的搜索條件的document,relevance score會更高,也就會優先被返回。
GET /forum/article/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "blog"
}
}
],
"should": [
{
"match": {
"title": {
"query": "elasticsearch"
}
}
},
{
"match": {
"title": {
"query": "spark",
"boost": 5
}
}
}
]
}
}
}
四、most fields評分算法
GET /forum/article/_search
{
"query": {
"bool": {
"should": [
{ "match": { "title": "java solution" }},
{ "match": { "content": "java solution" }}
]
}
}
}
按照多個字段的綜合匹配情況來計算整體分值,不會因為某個字段的匹配對最高而干擾最終結果,這點是與best fields的區別。
計算每個document的relevance score:每個query的分數之和,乘以matched query數量,除以總query數量,比如:總共2個match :
- doc4的情況是這樣:
doc4 跟match1 部分匹配,有一個"java" 分值1.1
doc4 跟match2 部分匹配,有一個"solution" 分值1.2
每個query的分數之和:1.1 + 1.2 = 2.3
matched query數量 : 2
總query數量 :2
2.3 * 2 / 2 = 2.3 - doc5的情況是這樣
doc5 跟match1不匹配,沒有分值
doc5 跟match2匹配,匹配度很高,有 "java solution" 分值為2.3
每個query的分數之和:2.3
matched query數量 :1
總query數量 : 2
2.3 * 1 / 2 = 1.15
doc5的分數 = 1.15 < doc4的分數 = 2.3
還有一些內容暫未記錄, Elasticsearch頂尖高手系列課程之高手進階篇
五、best fields策略
搜索到的結果,應該是某一個field中匹配到了盡可能多的關鍵詞,被排在前面;而不是盡可能多的field匹配到了少數的關鍵詞,排在了前面
dis_max語法,直接取多個query中,分數最高的那一個query的分數,完全不考慮其他字段的分數
GET /forum/article/_search
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "java solution" }},
{ "match": { "content": "java solution" }}
]
}
}
}
1.使用tie_breaker 優化 dis_max
使用tie_breaker將其他query的分數也考慮進去
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
}
}
}