Elasticsearch筆記-深入查詢
上一篇筆記Elasticsearch筆記-索引與查詢我們介紹了ES的簡單的增刪查改,這一次我們深入ES較為複雜的查詢,比如SQL中常用的select in 、模糊查詢、返回部分欄位等等。
一般來說,ES的真正用途在於分散式的搜尋引擎,由於其穩定快速的查詢效能又被當做資料庫使用。
承接上一篇資料,此時posts索引article型別中的資料如下:
{
"hits": {
"total": 4,
"max_score": 1,
"hits": [{
"_index": "posts",
"_type ": "article",
"_id": "5",
"_score": 1,
"_source": {
"id": 5,
"name": "生活日誌",
"author": "wthfeng",
"date": "2015-09-21",
"contents": "這是日常生活的記錄"
}
}, {
"_index ": "posts",
"_type": "article",
"_id": "4",
"_score": 1,
"_source": {
"id": 4,
"name": "javascript指南",
"author": "wthfeng",
"date": "2016-09-21",
"contents": "js的權威指南"
}
}, {
"_index": "posts",
"_type": "article",
"_id": "2",
"_score": 1,
"_source": {
"id": 2,
"name": "更新後的文件",
"author": "wthfeng",
"date": "2016-10-23",
"contents": "這是我的javascript學習筆記",
"brief": "簡介,這是新加的欄位"
}
}, {
"_index": "posts",
"_type": "article",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"name": "ES更新過的文件",
"author": "wthfeng",
"date": "2016-10-25",
"contents": "這是更新內容"
}
}]
}
}
1. 返回指定欄位(fields)
檢視我們的返回結果,每一個都帶有_source
欄位,裡面包含原始的資料。我們都是從這個欄位查詢出所需的結果。返回_source
欄位是預設的行為,如果我們只想返回某些欄位,那這些欄位在建立索引時必須開啟store
欄位。
上一篇定義的article對映部分:
{
"properties": {
"id": {
"type": "long",
"store": "yes" //開啟儲存
},
//......省略其他欄位
"contents": {
"type": "string",
"store": "no" //未開啟儲存,預設
}
}
}
現在要求返回文章名稱帶文件
兩詞的所有文章,且只返回id
和name
欄位。
curl localhost:9200/posts/article/_search?pretty -d @search.json
{
"fields": ["id", "name"],
"query": {
"match": {
"name": "文件"
}
}
}
返回資料部分
{
"hits": {
"total": 2,
"max_score": 0.53033006,
"hits": [{
"_index": "posts",
"_type": "article",
"_id": "2",
"_score": 0.53033006,
"fields": {
"name": ["更新後的文件"],
"id": [2]
}
}, {
"_index": "posts",
"_type": "article",
"_id": "1",
"_score": 0.16273327,
"fields": {
"name": ["ES更新過的文件"],
"id": [1]
}
}]
}
}
可見結果只有指定的欄位。且用fields
欄位代替了_source
欄位。類似SQL中:
select id,name from article where name like '%文件%'
- 如果查詢中沒有
fields
欄位,那預設返回_source欄位- 雖然返回更少欄位,但返回_source欄位比返回多個儲存欄位效能要好,所以無特殊要求,返回
_source
較好。
2. 多詞條查詢(terms)
多詞條查詢類似於SQL中的in
操作符。可以匹配在查詢內容中含有的多個詞條。注意,terms
匹配的是未經分析的詞條,也就是必須完全匹配。
查詢16年10月23號和25號發表的文章
curl localhost:9200/posts/article/_search -d @search.json
{
"query":{
"terms":{
"date":["2016-10-23","2016-10-25"]
}
}
}
注意:terms查詢的詞是未經分析的。它相當於term的複數版本。
類似於SQL:
select * from article where date in('2016-10-23','2016-10-25')
3. 範圍查詢(range)
範圍查詢(range)即返回指定範圍的文件,多用於數值型和日期型中。
查詢日期在10月23日及之前發表的,且文章名含有“指南”兩字文章。
curl localhost:9200/posts/article/_search?pretty -d @search.json
{
"query":{
"range":{
"date":{
"lte":"2016-10-23"
}
}
}
}
結果正確返回,這裡就不貼了。範圍查詢支援以下引數:
- gte :大於或等於
- gt :大於
- lte :小於或等於
- lt :小於
此例在SQL中很容易表示:
select * from article where date <= '2016-10-23'
4. 排序(sort)
預設的ES按文件的相關度排序,即與指定查詢吻合度最高的排在前面。如果我們想修改預設排序,需使用sort
欄位與query
欄位並列。
查詢文件內容含有”的”字所有文件並按日期、id排序
curl localhost:9200/posts/article/_search?pretty -d @search.json
{
"query":{
"match":{
"contents":"的"
}
},
"sort":[
{"date":"desc"},
{"id":"asc"}
]
}
sort接收一個數組,可以指定多個排序欄位,用asc
或desc
指定正序倒序
SQL 語句為
select * from article where contents like '%的%' order by date desc,id asc
預設欄位的排序
預設情況下,如果某文件沒有指定的排序欄位或該值為null,那麼,如果升序排,該文件排在最前面,倒序排排在最後面。也就是預設值的文件序列號是最小的。
我們可以用missing
修改這種預設行為。_first
指定排在最前列,_last
指定排在最後列。還可指定具體數值,則預設值就當做此值。
將預設值都放在前列
{
"query":{
"match":{
"contents":"的"
}
},
"sort":[
{"date":{
"order":"desc",
"missing":"_first"
}},
{"id":{
"order":"asc",
"missing":"_first"
}}
]
}
布林查詢(bool)
是時候將這些查詢聚在一起了,布林查詢負責此工作。類似於SQL中and
和or
等的作用
在布林查詢中
- should : 類似於
or
,可以匹配條件也可以不匹配- must : 類似於
and
,必須匹配- must_not : 類似於
!=
,必須不匹配
以上關鍵字需包含在bool
語句中。
查詢16年10月以來名稱含有“ES”的文件,且id不為1
{
"query": {
"bool": {
"should": {
},
"must": [{
"match": {
"name": {
"query": "ES"
}
}
}, {
"range": {
"date": {
"gte": "2016-10-01"
}
}
}],
"must_not": {
"term": {
"id": "1"
}
}
}
}
}
需要注意的是查詢的格式要求,should、must、must_not可以帶一個或多個查詢條件。注意無論怎樣的查詢條件都首先滿足json的格式要求。
上面寫成SQL類似於
select * from article where name like '%ES%' and date > '2016-10-01' and id !=1
———————end ———————–