Elaticsearch 有非常好的查詢效能,以及非常強大的查詢語法。在一定場合下可以替代RDBMS做為OLAP的用途。但是其官方查詢語法並不是SQL,而是一種Elasticsearch獨創的DSL。主要是兩個方面的DSL:
- Query DSL(https://www.elastic.co/guide/…) 相當於SQL裡的 WHERE 部分,實現各種各樣的過濾文件的方式
- Aggregation DSL (https://www.elastic.co/guide/… ) 相當於SQL裡的 GROUP BY 部分,實現文件按條件聚合並求一些指標(metric),比如求和求平均這些
這兩個DSL說實話是不好學習和理解的,而且即便掌握了寫起來也是比較繁瑣的,但是功能卻非常強大。本系列文章是為了兩個目的:
- 通過類比SQL的概念,實驗並學習Elasticsearch聚合DSL的語法和語義
- 用 python 實現一個翻譯器,能夠使用 SQL 來完成 Elasticsearch 聚合DSL一樣的功能。這個小指令碼可以在日常工作中做為一件方便的利器
基礎Elasticsearch知識(比如什麼是文件,什麼是索引)這裡就不贅述了。我們的重點是學習其查詢和聚合的語法。在本章中,我們先來準備好樣本資料。選擇的樣本資料是全美的股票列表(http://www.nasdaq.com/screeni…)。選擇這份資料的原因是因為其維度比較豐富(ipo年份,版塊,交易所等),而且有數字欄位用於聚合(最近報價,總市值)。資料下載為csv格式(https://github.com/taowen/es-…),並且有一個匯入指令碼(https://github.com/taowen/es-…)
下面是匯入Elasticsearch的mapping(相當於關係型資料庫的表結構定義):
{
"symbol": {
"properties": {
"sector": {
"index": "not_analyzed",
"type": "string"
},
"market_cap": {
"index": "not_analyzed",
"type": "long"
},
"name": {
"index": "analyzed",
"type": "string"
},
"ipo_year": {
"index": "not_analyzed",
"type": "integer"
},
"exchange": {
"index": "not_analyzed",
"type": "string"
},
"symbol": {
"index": "not_analyzed",
"type": "string"
},
"last_sale": {
"index": "not_analyzed",
"type": "long"
},
"industry": {
"index": "not_analyzed",
"type": "string"
}
},
"_source": {
"enabled": true
},
"_all": {
"enabled": false
}
}
}
對於把 Elasticsearch 當作資料庫來使用,預設以下幾個設定
- 把所有欄位設定為 not_analyzed
- _source 開啟,這樣就不用零散地儲存每個欄位了,大部分情況下這樣更高效
- _all 關閉,因為檢索都是基於 k=v 這樣欄位已知的查詢的
執行python import-symbol.py
匯入完成資料之後,執行
GET http://127.0.0.1:9200/symbol/_count
返回
{"count":6714,"_shards":{"total":3,"successful":3,"failed":0}}
可以看到文件已經被匯入索引了。除了匯入一個股票的列表,我們還可以把歷史的股價給匯入到資料庫中。這個資料比較大,放在了網盤上下載(https://yunpan.cn/cxRN6gLX7f9md 訪問密碼 571c)(http://pan.baidu.com/s/1nufbLMx 訪問密碼 bes2)。執行python import-quote.py
匯入
"quote": {
"_all": {
"enabled": false
},
"_source": {
"enabled": true
},
"properties": {
"date": {
"format": "strict_date_optional_time||epoch_millis",
"type": "date"
},
"volume": {
"type": "long"
},
"symbol": {
"index": "not_analyzed",
"type": "string"
},
"high": {
"type": "long"
},
"low": {
"type": "long"
},
"adj_close": {
"type": "long"
},
"close": {
"type": "long"
},
"open": {
"type": "long"
}
}
}
從 mapping 的角度,和表結構定義是非常類似的。除了_source,_all和analyzed這幾個概念,基本上沒有什麼差異。Elasticsearch做為資料庫最大的區別是 index/mapping 的關係,以及 index 通配這些。