DSL的誕生 | 複雜sql轉成Elasticsearch DSL深入詳解
源自死磕ElasticsearchQQ群(626036393)中的一個問題:
問題如下:
where (position=ES or work=ES or content=ES) and academic=本科 and (city=北京 or city=深圳)
怎麼構建ES的查詢條件?
我的問題拆解與實現如下:
1、sql語句轉成DSL有哪些方法?
方案一:藉助工具 NLP團體開發的Elasticsearch-sql;
2.X安裝過,5.X沒有再安裝。
方案二:藉助工具ElasticHQ的自動轉換模組:
方案一、方案二和Github上其他語言開發的sql轉DSL工具對簡單的sql生成的DSL相對準確,但對於複雜的sql生成的不一定精確。(如上所示)
方案三:徒手生成。
2、如何根據複雜的sql語句生成ES的DSL查詢語句呢?
步驟1:拆解
where (position=ES or work=ES or content=ES) and academic=本科 and (city=北京 or city=深圳)
這個sql語句由幾部分組成呢?
以and作為拆分,共分為3部分:
三個部分sql用and銜接,轉換為DSL對應最外層must;
第一部分: position=ES or work=ES or content=ES
三個子條件sql用or銜接,轉換DSL對應should;
第二部分: academic=本科
單一條件轉換為DSL對應term精確匹配;
第三部分: city=北京 or city=深圳
city的兩個or語句轉換為DSL對應terms多詞精確匹配。
上面的sql都用的=號,假定不需要分詞,我們統一採用termquery和termsquery實現。
引申:
如果需要分詞,更換為matchquery或者match_parsequery即可。
如果需要模糊匹配,更換為wildcardquery介面。
步驟2:套bool多條件檢索DSL模板
複雜bool多條件檢索DSL模板:
包含了:查詢/檢索、聚合、排序、指定欄位輸出、輸出起點、輸出多少等資訊。
{
"query": {
"bool ": {
"must": [],
"must_not": [],
"should": []
}
},
"aggs": {
"my_agg": {
"terms": {
"field": "user",
"size": 10
}
}
},
"highlight": {
"pre_tags": [
"<em>"
],
"post_tags": [
"</em>"
],
"fields": {
"body": {
"number_of_fragments": 1,
"fragment_size": 20
},
"title": {}
}
},
"size": 20,
"from": 100,
"_source": [
"title",
"id"
],
"sort": [
{
"_id": {
"order": "desc"
}
}
]
}
簡單bool多條件查詢DSL模板:
只包含查詢。
{
"query": {
"bool": {
"must": [],
"must_not": [],
"should": []
}
}
}
以上根據我們的sql特點,簡單模板即能滿足要求。
步驟3:構造生成DSL
根據,步驟1、步驟2,可以構思出根據sql轉換後的DSL應該:
1)最外層bool
2)第二層:must 三個並行條件
3)第三層:各自的匹配條件。(存在bool巢狀bool的情況)
3、動動手,驗證下。
3.1 建立索引(自動生成mapping)
put test_index_01
3.2 提交資料
post test_index_01/test_type_01/1
{
"no":"1",
"city":"北京",
"academic":"專科",
"content":"ES",
"position":"ES",
"work":"ES"
}
post test_index_01/test_type_01/2
{
"no":"2",
"city":"天津",
"academic":"本科",
"content":"ES",
"position":"ES",
"work":"ES"
}
post test_index_01/test_type_01/3
{
"no":"3",
"city":"深圳",
"academic":"本科",
"content":"ES",
"position":"ES2",
"work":"ES3"
}
post test_index_01/test_type_01/4
{
"no":"4",
"city":"北京",
"academic":"本科",
"content":"ES1",
"position":"ES2",
"work":"ES"
}
插入後ES-head外掛控制檯查詢結果:
3.3 完成檢索
post test_index_01/_search
{
"query": {
"bool": {
"must": [
{
"terms": {
"city.keyword": [
"北京",
"深圳"
]
}
},
{
"term": {
"academic.keyword": "本科"
}
},
{
"bool": {
"should": [
{
"term": {
"content.keyword": "ES"
}
},
{
"term": {
"position.keyword": "ES"
}
},
{
"term": {
"work.keyword": "ES"
}
}
]
}
}
]
}
},
"size": 10,
"from": 0
}
注意:
沒有做分詞,做的精確匹配,所以加了”.keyword”。
3.4 返回結果
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1.0577903,
"hits": [
{
"_index": "test_index_01",
"_type": "test_type_01",
"_id": "4",
"_score": 1.0577903,
"_source": {
"no": "4",
"city": "北京",
"academic": "本科",
"content": "ES1",
"position": "ES2",
"work": "ES"
}
},
{
"_index": "test_index_01",
"_type": "test_type_01",
"_id": "3",
"_score": 0.8630463,
"_source": {
"no": "3",
"city": "深圳",
"academic": "本科",
"content": "ES",
"position": "ES2",
"work": "ES3"
}
}
]
}
}
4、小結
實踐是檢驗真理的唯一標準!
如有不同意見,歡迎拍磚探討!
——————————————————————————————————
更多ES相關實戰乾貨經驗分享,請掃描下方【銘毅天下】微信公眾號二維碼關注。
(每週至少更新一篇!)
和你一起,死磕Elasticsearch!
——————————————————————————————————
2017.11.16 22:39 於家中床前