Elasticsearch 連線查詢
在一般的關係型資料庫中,都支援連線操作。
在ES這種分散式方案中進行連線操作,代價是十分昂貴的。
不過ES也提供了相類似的操作,支援水平任意擴充套件,實現連線的效果。
ES中的連線
在ES中支援兩種連線方式:巢狀查詢 和 has_child、has_parent父子查詢
巢狀查詢:
文件中包含巢狀的欄位,這些欄位以陣列的形式儲存物件,這樣每個巢狀的子物件都可以被搜尋。
has_child、has_parent父子查詢:
父子文件是儲存在同一個索引中的不同型別,在索引資料前定義父子關係。在父子查詢中,父子關係通過型別引用。
巢狀查詢
巢狀型別需要實現定義好mapping:
{ "type1" : { "properties" : { "obj1" : { "type" : "nested" } } } }
定義好後,type1中就有了obj1這個子物件,然後就可以通過巢狀查詢查詢相關的內容:
{ "nested" : { "path" : "obj1", "score_mode" : "avg", "query" : {"bool" : { "must" : [ { "match" : {"obj1.name" : "blue"} }, { "range" : {"obj1.count" : {"gt" : 5}} } ] } } } }
注意其中幾個引數:
1 path 定義了巢狀的物件
2 score_mode 定義裡巢狀物件計算的分數與當前查詢分數的處理方式,有avg,sum,max,min以及none。none就是不做任何處理,其他的看字面意思就好理解。
3 query/filter是查詢的方式,內部定義了針對巢狀物件的查詢,注意內部的查詢一定要是用全路徑,即針對obj1的name欄位的查詢,要寫obj1.name。
巢狀查詢會在執行子查詢的時候自動觸發,然後把結果返回給當前文件的查詢。
父子查詢
父子關係也需要在之前定義mapping,不過與一般的對映不同,它的定義方式如下:
PUT my_index { "mappings": { "my_parent": {}, "my_child": { "_parent": { "type": "my_parent" } } } } PUT my_index/my_parent/1 { "text": "This is a parent document" } PUT my_index/my_child/2?parent=1 { "text": "This is a child document" } PUT my_index/my_child/3?parent=1 { "text": "This is another child document" } GET my_index/my_parent/_search { "query": { "has_child": { "type": "my_child", "query": { "match": { "text": "child document" } } } } }
這樣就代表,my_child這個型別的父型別是my_parent,這樣就聲明瞭一種父子關係。然後再索引資料時,指定父子對應的關係。
has_child查詢
這個查詢會檢查子文件,如果子文件滿足查詢條件,則返回父文當。
{ "has_child" : { "type" : "blog_tag", "query" : { "term" : { "tag" : "something" } } } }
通過score_mode欄位,可以指定子文件返回的分值的處理方式。與巢狀類似,它也有avg,sum,max,min和none幾種方式。
{ "has_child" : { "type" : "blog_tag", "score_mode" : "sum", "query" : { "term" : { "tag" : "something" } } } }
另外,也可以指定子文件匹配的最小數目和最大數目。
{ "has_child" : { "type" : "blog_tag", "score_mode" : "sum", "min_children": 2, "max_children": 10, "query" : { "term" : { "tag" : "something" } } } }
has_parent查詢
has_parent查詢與has_child類似,它是去檢查父文件那個是否匹配,然後返回父文件對應的子文件。
{ "has_parent" : { "parent_type" : "blog", "query" : { "term" : { "tag" : "something" } } } }