iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
0
Elastic Stack on Cloud

Elastic 戰台股系列 第 19

[Day19] 選股程式實作 - Script Query (2)

  • 分享至 

  • twitterImage
  •  

今天接續昨天挖的坑,來理解一下 Script Query 的靈魂: Painless 語言。

Painless 介紹

在 Elasticsearch 裡支援了利用 Script 對客製化的查詢語句 (custom expression) 進行文件查找,簡單來說就是把 「Document 拉到本地端進行邏輯運算」的動作,直接在 Elasticsearch 的 Runtime 中執行。對 Client 端的應用的好處來說,只要專注在「資料」本身。我想信對巨量資料處理上,在 Elasticsearch 中進行運作,有更大的效能優勢,只是我目前暫時無法探索那部分,留待日後研究。

在較舊版的 Elasticsearch 中,原本也支援 Groovy,Javascript 及 Python 等腳本語言,但 6.0 後都已經停止支援。目前 Elasticsearch 預設支援的腳本語言即為 Painless。

Painless 是以「安全性」與「效能」為前題,專為 Elasticsearch 設計的腳本語言。語法上與 Java 類似,但包含了額外的特性 (這等到寫 Code 時再來探索)。Painless 腳本經過編繹後,會運行在標準的 JVM runtime。雖然「效能」是一大特色,但 Script 使用上仍有效能上的考量 (官方文件),先挖個坑,不確定這場鐵人賽有沒有機會探索到。

如何使用 Script

Script 的 Query DSL 如下:

"script": {
    "lang":   "...",  <== 預設是 painless 
    "source" | "id": "...",  <== source: inline; id: stored script
    "params": { ... } 
 }

通常,script query 會用在 filter 內文中。套路! 到 Kibana Dev Tools 來玩玩看。目標,搜尋股價在 10 元以上,100 元以下的個股。

GET /history-prices-daily/_search
{
    "query" : {
      "bool": {
				"must": [
          {"match": {
            "date": "2020-09-23"
          }}
        ],
        "filter": {
          "script": {
            "script": {
              "lang": "painless",
              "source": "doc['close'] >= params.low_price && doc['close'] <= params.high_price",
              "params": {
                "low_price": 10,
                "high_price": 100
              }
            }
          }
        }
      }
    }
}

登楞… 報錯:

"caused_by" : {
	"type" : "class_cast_exception",
	"reason" : "Cannot apply [>] operation to types [org.elasticsearch.index.fielddata.ScriptDocValues.Doubles] and [java.lang.Integer]."
}

根據文檔 ,這種類似 Map 的取值方式,應該是沒問題的,但事實証明,要把 Inline script 內的取值方式改成:

"doc['close'].**value** >= params.low_price && doc['close'].**value** <= params.high_price"

找時間要深入理解一下差異。結果找到 728 檔個股在這個股價範圍:
https://ithelp.ithome.com.tw/upload/images/20201002/20129624mjvDXdHDJM.png
回到 Elasticsearch DSL 來試試:

s = Search(using=es, index="history-prices-daily") \
    .query("match", date="2020-09-23") \
    .filter( "script", script={
                        "lang": "painless",
                        "source": "doc['close'].value >= params.low_price && doc['close'].value <= params.high_price",
                        "params": {
                            "low_price":  10,
                            "high_price": 100
                        }
                       }
    )
print(response['hits']['total']['value'])
// 728

得到一樣的結果。

明天就用 Script Query 讓選股程式再跑起來吧!


上一篇
[Day18] 選股策略實作 - Script Query (1)
下一篇
[Day20] 選股程式實作 - 整合 Script Query 的 20週線選股策略
系列文
Elastic 戰台股30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言