iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
Software Development

由淺入深來探討Elasticsearch,從基礎語法到底層相關原理系列 第 18

【Day 18】由淺入深來探討Elasticsearch - Searching for Data (2)

  • 分享至 

  • xImage
  •  

我們今天把基礎查詢方法的坑填上~

今天會介紹

  1. phrase search
  2. Fuzzy match query
  3. Fuzzy query
  4. search object, nested, and join field
  5. relevance score
  6. search multiple fields

phrase search

GET /test_phrase/_search
{
  "query": {
    "match_phrase": {
      "desc": "value"
    }
  }
}
  • 因為查詢時除了要注意想要搜尋的document需要包含所有輸入的搜尋值
  • 搜尋時也要注意順序,並且各搜尋字之間不能有其他單字
// 原始文檔
"desc": "I'm testing a Function!"
// 搜尋語句
"desc": "m test" // 會找不到
"desc": "test a function" // 可以找到
  • 可以設置analyzer,對應想查找的field的analyzer
  • 也可以設置slop來讓順序不要那麼嚴謹(預設0)
{
  "query": {
    "match_phrase": {
      "desc": "value",
			"analyzer": "your_analyzer",
			"slop": 1
    }
  }
}

這邊說一下slop:

  • 設置1就代表你輸入的單字能做一次移動,以此類推
position 1 position 2 position 3
Document Es is good
your query is ES
first slop ES/is
second slop ES
  • 在實際應用時,slop不一定要設最小,因為相關分數還是會影響搜尋結果的排名

Fuzzy match query

  • 在match query中添加fuzziness參數
  • 相當於模糊查詢
  • 設置的數字代表能容忍的最大編輯距離(Levenshtein Edit Distance)
  • 變更一次相當於
    • box → fox (改變一次)
    • black → lack (刪除一次)
    • sic → sick (匯入一次)
    • ab → ba (互換一次)
    • Damerau–Levenshtein distance讓互換一次能算作一次,不然一般是算兩次
  • 每個查詢單字是獨立計算編輯次數的,所以通常設1就很夠用了。也可設auto(會根據單字長短來變更數字)
  • 非常消耗cpu,且設太大的編輯會導致結果非常不可控,根據研究來說設2就能包含大部分人為失誤

Fuzzy query:

  • 跟上述的fuzzy match query類似,但是查詢時是term query而不是text要注意
  • 具備fuzziness以外,還能調整其他參數prefix_length, max_expansions, transpostions(match也通用)

Search object, nested

  • 搜尋一般的object field直接用 field_name.sub_field_name的方式就好
  • nested field則如下
// 示範index
PUT /test_nested_index
{
  "mappings": {
    "properties": {
      "obj": {
        "type": "nested"
      }
    }
  }
}

// query
GET /test_nested_index/_search
{
  "query": {
    "nested": { //需要表明是nested
      "path": "obj", // 表明路徑是哪個nested field
			"inner_hits": {
				"name": "my_hits",
				"size": 3 // 減少inner_hits的返回數量能加速查詢速度
			},
      "query": {
        "match": {
		      "obj.xxx": ""
        }
      }
    }
  }
}
  • nested query如果有匹配到結果的話,會返回整個parent document
  • 因為上述的特性,加上ES不會告訴我們查詢是因為匹配parent還是nested內部,所以可以使用添加inner hits,如果有匹配,返回如下:
"hits": [
     {
        "_index": ...,
        "_type": ...,
        "_id": ...,
        "inner_hits": {
           "<inner_hits_name>": {
              "hits": {
                 "total": ...,
                 "hits": [
                    {
                       "_id": ...,
                       ...
                    },
                    ...
                 ]
              }
           }
        },
        ...
     },
     ...
]

Search join field

  • 因為join field也就是兩個文檔有親子關係,因此會搭配has_child跟has_parent來查詢
  • 跟nested field一樣,ES也不會直接顯示為何文檔匹配,所以一樣可以添加inner_hits
GET /test_join_search/_search
{
  "query": {
    "has_child": { // 依照需求決定是has_parent還是找has_child
      "type": "my_child", 
      "query": {
        "match": {
          "number": 1
        }
      },
      "inner_hits": {}
    }
  }
}

Relevance score

  • ES在對查詢語句進行文檔的匹配時,都會計算查詢語句跟文檔之間的相關程度,並且由特定公式所算出相關分數後進行排序
  • 默認情形下是使用practical scoring function(BM25)這個計算模型,主要會根據幾個參數進行計算
    • term frequency(tf):代表查詢語句在文檔中出現的頻率,出現頻率越高通常代表關聯性越強
    • inverse document frequency(idf):如果被分切後的term出現在越多的文檔中,會被認為不那麼重要,反之出現頻率越少加權值會更高
    • field-length normalization:就是看查詢語句跟文檔字數的比例,如果佔比很高就代表很重要
  • 我們也能透過添加不同參數來控制特定情形的加權值(後面會一一介紹),或是透過function score來改寫算法
  • 我們能用explain API來看計算的過程
GET /test_phrase/_explain/1
{
  "query": {
    "match": {
      "desc": "the"
    }
  }
}

https://ithelp.ithome.com.tw/upload/images/20230920/20161866leBpOnfrU4.png

  • 可以看到會針對每個分數解釋是由哪些參數加權計算出來的

Search multiple fields

  • 我們也能同時查詢不同欄位,並且依據你想要哪邊匹配到更加重要,去分配加權值
  • 因為雖然是使用多欄位查詢,但是假如某一欄的分數較高,會直接只拿那一欄的分數來當作該文檔的相關分數,其他欄位有匹配到也不計分
    • 可以設置tie_breaker讓其他欄位*該參數也添加進相關分數中
GET /test_phrase/_search
{
  "query": {
    "multi_match": {
      "query": "cheese",
      "fields": ["name^2", "desc"], // 讓name匹配時,分數*2
			"tie_breaker": 0.3
    }
  }
}

明天我們會開始進到compound queries
先前我們都只做單一查詢,沒有用到什麼and跟or或是must等等概念
而明天開始則會介紹複合的查詢語句,讓我們更能夠去貼近使用時的查詢邏輯~

參考資料
Match phrase query:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html
fuzziness:
https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness
match fuzzy參數詳解:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html
nested query:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
joining query:
https://www.elastic.co/guide/en/elasticsearch/reference/current/joining-queries.html
inner hist:
https://www.elastic.co/guide/en/elasticsearch/reference/current/inner-hits.html#inner-hits
relevance score:
https://opster.com/guides/elasticsearch/search-apis/elasticsearch-scoring-understanding-the-explain-api/


上一篇
【Day 17】由淺入深來探討Elasticsearch - Searching for Data (1)
下一篇
【Day 19】由淺入深來探討Elasticsearch - Compound queries
系列文
由淺入深來探討Elasticsearch,從基礎語法到底層相關原理30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言