2.Elasticsearch查詢-請求體查詢、排序
一、請求體查詢
請求體 search API, 之所以稱之為請求體查詢(Full-Body Search),因為大部分參數是通過http請求體而非查詢字符串來傳遞的。
請求體查詢:不僅可以處理自身的查詢請求,還允許你對結果進行片段強調(高亮)、對所有或部分結果進行聚合分析,同時還可以給出 你是不是想找 的建議,這些建議可以引導使用者快速找到他想要的結果。
某些特定語言(特別是 JavaScript)的 HTTP 庫是不允許 GET 請求帶有請求體的,可以用POST代替。
1、空查詢
空查詢,空的請求體會返回所有索引中的所有文檔
GET /_search
{}
用一個查詢字符串,在多個索引庫中和多個types中查詢:
GET /index_2014*/type1,type2/_search
{}
使用 from 和 size 參數分頁:
GET /_search
{
"from": 30,
"size": 10
}
2、查詢表達式(Query DSL)
使用
將查詢語句傳遞給query參數
GET /_search
{
"query": YOUR_QUERY_HERE
}
查詢語句結構
典型結構:
{ QUERY_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } }
針對某個字段:
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
例子:
GET /_search
{
"query": {
"match": {
"city": "Shaft"
}
}
}
match_all查詢
空查詢(empty search),在功能上等價於使用 match_all 查詢:
GET /_search
{
"query": {
"match_all": {}
}
}
合並查詢語句
葉子語句:用於將查詢字符串和一個字段(或者多個字段)對比,match
復合語句:主要用於合並其它查詢語句,bool
GET /_search
{
"query": {
"bool": {
"must":{"match":{"state":"KY"}},
"must_not":{"match":{"city:":"Yettem"}},
"should":{"match":{"address":"382 Columbia Street"}},
"filter": { "range": { "age" : { "gt" : 30 }} }
}
}
}
3、查詢與過濾
過濾:
查詢被設置成一個“不評分”或者“過濾”查詢。匹配或者不匹配。
查詢:
查詢就變成了一個“評分”的查詢。一個評分查詢計算每一個文檔與此查詢的相關程度,同時將這個相關程度分配給表示相關性的字段_score,並且按照相關性對匹配到的文檔進行排序。
註意:
"filter" 這個詞表示不評分、只過濾情況下的查詢。== "filter" 、 "filtering query" 和 "non-scoring query"
"query" 我們指的是 "scoring query"
性能差異:
過濾查詢(Filtering queries:計算快,經常用不評分查詢結果稀少,結果會被緩存到內存中以便快速讀取,所以有各種各樣的手段來優化查詢結果。
評分查詢(scoring queries):計算費力,查詢結果並不緩存。
4、最重要的查詢
match_all查詢
匹配所有文檔,默認查詢方式。它經常與 filter 結合使用
{ "match_all": {}}
match查詢
標準查詢,無論你在任何字段上進行的是全文搜索還是精確查詢。
全文字段使用時,在執行查詢前,它將用正確的分析器去分析查詢字符串:
{ "match": { "tweet": "About Search" }}
在一個精確值字段使用,例如數字、日期、布爾或者一個 not_analyzed 字符串字段,它會精確匹配給定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
multi_match 查詢
可以在多個字段上執行相同的 match 查詢:
GET /_search
{
"query": {
"multi_match": {
"query": "728",
"fields": [ "address", "account_number" ]
}
}
}
解釋:查詢在address和account_number字段帶有728字符串的文檔。
range查詢
找出那些落在指定區間內的數字或者時間:
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
操作符如下:
- gt 大於
- gte 大於等於
- lt 小於
- lte 小於等於
term查詢
被用於精確值匹配,這些精確值可能是數字、時間、布爾或者那些 not_analyzed 的字符串:
{ "term": { "age": 26 }}
{ "term": { "date": "2014-09-01" }}
{ "term": { "public": true }}
{ "term": { "tag": "full_text" }}
註意:以上某一行
terms查詢
terms 查詢和 term 查詢一樣,但它允許你指定多值進行匹配。如果這個字段包含了指定值中的任何一個值,那麽這個文檔滿足條件:
GET /_search
{
"query": {
"terms": { "age": [39,38,30 ] }
}
}
解釋:年齡為39或38或30的文檔。
exists查詢、missing查詢
用於查找那些指定字段中有值 (exists) 或無值 (missing) 的文檔:
GET /_search
{
"query": {
"exists": {
"field": "title"
}
}
}
解釋:查詢title字段有值的文檔
5、組合多查詢
可用bool查詢,它接受以下參數:
- must:文檔 必須 匹配這些條件才能被包含進來。
- must_not:文檔 必須不 匹配這些條件才能被包含進來。
- should:如果滿足這些語句中的任意語句,將增加_score ,否則,無任何影響。它們主要用於修正每個文檔的相關性得分。
filter:必須 匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔。
bool查詢
查找 title 字段匹配 how to make millions 並且不被標識為 spam 的文檔。那些被標識為 starred 或在2014之後的文檔,將比另外那些文檔擁有更高的排名。如果_兩者_都滿足,那麽它排名將更高:
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }},
{ "range": { "date": { "gte": "2014-01-01" }}}
]
}
}
增加帶過濾器的bool查詢
如果我們不想因為文檔的時間而影響得分,可以用 filter 語句來重寫前面的例子:
{
??? "bool": {
??????? "must":???? { "match": { "title": "how to make millions" }},
??????? "must_not": { "match": { "tag":?? "spam" }},
??????? "should": [
??????????? { "match": { "tag": "starred" }}
??????? ],
??????? "filter": {
????????? "range": { "date": { "gte": "2014-01-01" }} ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
??????? }
??? }
}
如果你需要通過多個不同的標準來過濾你的文檔,bool查詢本身也可以被用做不評分的查詢,簡單地將它放置到filter語句中並在內部構建布爾邏輯:
{
??? "bool": {
??????? "must":???? { "match": { "title": "how to make millions" }},
??????? "must_not": { "match": { "tag":?? "spam" }},
??????? "should": [
??????????? { "match": { "tag": "starred" }}
??????? ],
??????? "filter": {
????????? "bool": { ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
????????????? "must": [
????????????????? { "range": { "date": { "gte": "2014-01-01" }}},
????????????????? { "range": { "price": { "lte": 29.99 }}}
????????????? ],
????????????? "must_not": [
????????????????? { "term": { "category": "ebooks" }}
????????????? ]
????????? }
??????? }
??? }
}
constant_score查詢
可以使用它來取代只有 filter 語句的 bool 查詢,性能相同,但是簡潔:
{
??? "constant_score":?? {
??????? "filter": {
??????????? "term": { "category": "ebooks" } ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
??????? }
??? }
}
解釋:term 查詢被放置在 constant_score 中,轉成不評分的 filter。這種方式可以用來取代只有 filter 語句的 bool 查詢。
6、驗證查詢
validate-query API 可以用來驗證查詢是否合法:
GET /bank/address/_validate/query?
{
"query": {
"address" : {
"match" : "Avenue"
}
}
}
解釋不合法原因:
GET /bank/address/_validate/query?explain
{
"query": {
"address" : {
"match" : "Avenue"
}
}
}
二、排序與相關性
1、排序
在 Elasticsearch 中, 相關性得分 由一個浮點數進行表示,並在搜索結果中通過_score 參數返回, 默認排序是_score 降序。
使用 constant_score 查詢進行替代bool,讓所有文檔應用一個恒定分數(默認為 1 ),不是0:
GET /_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"user_id" : 1
}
}
}
}
}
2、按照字段的值排序
GET /_search
{
"query" : {
"bool" : {
"filter" : { "term" : { "age" : 40 }}
}
},
"sort": { "balance": { "order": "desc" }}
}
3、多級排序
假定我們想要結合使用 date和_score 進行查詢,並且匹配的結果首先按照日期排序,然後按照相關性排序:
GET /_search
{
"query" : {
"bool" : {
"must": { "match": { "tweet": "manage text search" }},
"filter" : { "term" : { "user_id" : 2 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
Query-string 搜索 也支持自定義排序,可以在查詢字符串中使用 sort 參數:
GET /_search?sort=date:desc&sort=_score&q=search
4、多值字段排序
情形:一個字段裏有多個值,並且這些值沒有順序,應該選擇哪個值排序。
對於數字或日期,你可以將多值字段減為單值,這可以通過使用 min 、 max 、 avg 或是 sum 排序模式 。 例如你可以按照每個 date 字段中的最早日期進行排序,通過以下方法:
"sort": {
"dates": {
"order": "asc",
"mode": "min"
}
}
5、字符串排序與多字段
一個簡單的方法是用兩種方式對同一個字符串進行索引,這將在文檔中包括兩個字段: analyzed 用於搜索, not_analyzed 用於排序。
為一個多字段映射如:
"tweet": { ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
??? "type":???? "string",
??? "analyzer": "english",
??? "fields": {
??????? "raw": {
??????????? "type":? "string",
??????????? "index": "not_analyzed"
??????? }
??? }
}
- tweet?主字段與之前的一樣: 是一個?analyzed?全文字段。
- 新的?tweet.raw?子字段是?not_analyzed.
現在,使用 tweet 字段用於搜索,tweet.raw 字段用於排序:
GET /_search
{
"query": {
"match": {
"tweet": "elasticsearch"
}
},
"sort": "tweet.raw"
}
註意:以全文 analyzed 字段排序會消耗大量的內存
2.Elasticsearch查詢-請求體查詢、排序