教你快速從SQL過度到Elasticsearch的DSL查詢
前言
Elasticsearch太強大了,強大到跟python一樣,一種查詢能好幾種語法。
其實我們用到的可能只是其中的一部分,比如:全文搜索。
我們一般是會將mysql的部分欄位導入到es,再查詢出相應的ID,再根據這些ID去資料庫找出來。
問題來了:數據導入到es後,很多人都要面對這個es的json查詢語法,也叫DSL,如下
於是一堆新詞來了,比如:filter、match、multi_match、query、term、range,容易讓沒學過的人抵觸。
如果正常開發業務的程式設計師,只關心原先怎麼用sql查詢出來的數據,在es中查詢出來。
sql查詢定位,一般常用的是:=、!=、>、<、and、or、in、between等等。
舉個例子,原先sql查詢一商品是這樣的
SELECT * FROM goods WHERE spu_id = "wp123" OR ( spu_id = "wp345" AND min_price = 30 )
對應到es是
{
"query": {
"bool": {
"should": [{
"term": {
"spu_id": "wp123"
}
},
{
"bool": {
"must": [{
"term": {
"spu_id": "wp345"
}
},
{
"term": {
"min_price": 30
}
}
]
}
}
]
}
}
}
sql和dsl是有一定對應關係的,下面把一些常用的總結下,讓不熟悉es能絲滑從sql過度
以下內容由chenqionghe傾情提供,祝你es使用愉快
bool-相當於一個括弧
用bool包含起來的{},相當用()包含了一個複合查詢語句,如上邊的
{
"bool": {
"must": [{
"term": {
"spu_id": "wp345"
}
},
{
"term": {
"min_price": 30
}
}
]
}
}
相當於
看到沒有就是這麼簡單
should-相當於or
must-相當於and
must_not-相當於 ! and
這個就相當於and取反了,
例如:
SELECT * FROM goods WHERE !(shop_id =79)
相當於
"query": {
"bool": {
"must_not": [
{
"term": {"shop_id": "79"}
}
]
}
}
}
term-相當於=
例如
SELECT * FROM goods WHERE shop_id =79
相當於
{
"query": {
"bool": {
"must": [
{
"term": {"shop_id": "79"}
}
]
}
}
}
terms-相當於in
例如
SELECT * FROM goods WHERE shop_id in (79,80,81)
相當於
{
"query": {
"bool": {
"must": [
{
"terms": {"shop_id": [79,80,81]}
}
]
}
}
}
between-相當於range
例如
SELECT * FROM goods WHERE id between 1000 and 10005
相當於
{
"query": {
"bool": {
"must": [{
"range": {
"id": {
"gte": 1000,
"lte": 10005
}
}
}]
}
}
}
is null-相當於exist
例如
SELECT * FROM goods WHERE id is not null
相當於
{
"query": {
"bool": {
"must_not": [{
"exists": {
"field": "id"
}
}]
}
}
}
match-類似match…AGAINST
這個match就相當於mysql的全文索引,關於mysql的全文索引,可以看一下這篇文章:從零開始學習MySQL全文索引
舉個查詢的例子,我要搜索包含 "海南 2018"的詞,如下
{
"query": {
"match": {
"name": "海南 2018"
}
}
}
這相當於把所有的「海南」和「2018」記錄找出來了,他們是一個or的關係。如果想同時匹配怎麼辦呢?
可以這樣,指定一個operator,默認是用的”or”,可以改成這樣
{
"query": {
"match": {
"name": {
"query": "海南 2018",
"operator": "and"
}
}
}
}
select-相當於includes
比如
SELECT id,name FROM goods WHERE id = 1765
相當於
{
"query": {
"bool": {
"must": [
{
"term": {
"id": 1765
}
}
]
}
},
"_source":{"includes":["id","name"]}
}
到這裡,差不多就已經可以絲滑地從sql過度到es的dsl了
一些常見問題
match和term的區別
match在匹配時會對所查找的關鍵詞進行分詞,然後按分詞匹配查找,而term會直接對關鍵詞進行查找。一般模糊查找的時候,多用match
query和filter
filter:只查詢出搜索條件的數據,不計算相關度分數
query:查詢出搜索條件的數據,並計算相關度分數,按照分數進行倒序排序
filter比query性能好,兩者可以一起使用
filtered和filter區別
filtered是比較老的的版本的語法。現在目前已經被bool替代。推薦使用bool。
老版本寫法
{
"query": {
"filtered": {
"query": {
"match": {
"text": "quick brown fox"
}
},
"filter": {
"term": {
"status": "published"
}
}
}
}
}
新版本寫法
{
"query": {
"bool": {
"must": {
"match": {
"text": "quick brown fox"
}
},
"filter": {
"term": {
"status": "published"
}
}
}
}
}
filter兩種用法
嵌套在bool下
{
"query": {
"bool": {
"must": {
"term": {
"term": {
"title": "kitchen3"
}
}
},
"filter": {
"term": {
"price": 1000
}
}
}
}
}
在根目錄下使用
{
"query": {
"term": {
"title": "kitchen3"
}
},
"filter": {
"term": {
"price": 1000
}
}
}
term和terms的區別
term相當於where =
terms相當於 where in (xx,xx,xx)
如果想要=於多次,得用多個term,而不是terms
還有一些內容,沒來得及寫,如order by、group by等等會陸續在這篇文章更新…