Elasticsearch 用 random_score 進行隨機抽樣

Posted on  May 9, 2021  in  Elasticsearch  by  Amo Chen  ‐ 2 min read

Elasticsearch 中存放大量的資料(或稱文件 document)時,一般難以片刻就遍訪每 1 筆資料,如果是為了驗證資料格式,或者需要資料進行實驗,此情況下可選擇用抽樣的方式進行,不僅可利用抽樣的方式預估整個資料庫的情況,也可以有效率地以部分資料進行實驗。

本文記錄如何以 function_score 結合 random_score 進行隨機抽樣。

本文環境

  • Elasticsearch 7.10.1

function_score & random_score

Elasticsearch 預設會將搜尋結果以文件的相關度進行排序,每 1 筆搜尋結果都有 1 個稱為 _score 的欄位,該欄位數值越高代表與搜尋關鍵字的相關度越高,代表越可能是使用者想要的搜尋結果。

但不見得預設的相關度排序方式適合所有類型的資料,因此 Elasticsearch 也提供控制搜尋結果排序的方式,也就是 function_score

function_score 提供若干控制相關度的方式(其它方式詳見文件 ),其中 random_score 可用以隨機為每 1 個文件產生 1 個介於 0 到 1 (不包含 1) 的隨機數作為 _score

如此一來,我們就能夠利用該函式隨機抽樣,例如以下語法隨機抽樣 1 筆資料:

POST /<index>/_search
{
   "query":{
      "function_score":{
         "random_score":{
         }
      }
   },
   "size": 1
}

p.s. 請將 <index> 改為你想要抽樣的 Elasticsearch index 名稱

p.s. 如果需要建立實驗環境,可參考 用 Docker 架設 Elasticsearch 實驗環境 一文

random_score 還可以設定 seed 參數,讓隨機數產生結果可以重現,因此設定 seed 理論上可以每次抽樣到相同的資料,設定 seed 之後仍需要設定 field 參數,告訴 Elasticsearch 以什麼欄位的值產生隨機數值,若不提供的話,預設會以 _id 欄位作為 field 的參數值,但是若以 _id 作為 field 參數值會消耗許多記憶體,若是 production 環境的 Elasticsearch 伺服器,記憶體的異常消耗可能會對服務造成影響,建議可以使用 _seq_no 做為 field 的參數值:

POST /<index>/_search
{
   "query":{
      "function_score":{
         "random_score":{
           "seed": 400,
           "field": "_seq_no"
         }
      }
   },
   "size": 1
}

關於 _seq_no 可以閱讀 Sequence IDs: Coming Soon to an Elasticsearch Cluster Near You 一文,基本上代表每 1 筆資料建立索引時的順序。

值得注意的是,即使設定好 seed 以及 field 仍不能 100% 保證抽樣到相同的資料,因為 Elasticsearch index 仍可能因為資料改變或者進行 merge 等原因造成抽樣結果改變。

更多 radom_score 範例

以下為更多關於 random_score 的範例。

隨機抽樣欄位中含有特定關鍵字的資料

p.s. 請將 <index> , <field><keyword> 改成你想要的值

POST /<index>/_search
{
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "<field>": {
                  "query": "<keyword>"
                }
              }
            }
          ]
        }
      },
      "random_score": {}
    }
  },
  "size": 1
}

結合 filter 隨機抽樣欄位中含有特定關鍵字的資料

p.s. 請將 <index> , <field> , <keyword> , <value> 改成你想要的值

POST /<index>/_search
{
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "<field>": {
                  "query": "<keyword>"
                }
              }
            }
          ],
          "filter": [
            {
              "range": {
                "<field>": {
                  "gte": <value>
                }
              }
            }
          ]
        }
      },
      "random_score": {}
    }
  },
  "size": 1
}

以上為 Elasticsearch 的 random_score 說明。

Happy Coding!

References

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html#function-random

對抗久坐職業傷害

研究指出每天增加 2 小時坐著的時間,會增加大腸癌、心臟疾病、肺癌的風險,也造成肩頸、腰背疼痛等常見問題。

然而對抗這些問題,卻只需要工作時定期休息跟伸展身體即可!

你想輕鬆改變現狀嗎?試試看我們的 PomodoRoll 番茄鐘吧! PomodoRoll 番茄鐘會根據你所設定的專注時間,定期建議你 1 項辦公族適用的伸展運動,幫助你打敗久坐所帶來的傷害!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!