學習須要先打好基礎,最後才能逐步深刻。今天來從新探索下ElasticSearch
的全文搜索。web
ElasticSearch中存在兩種搜索方式。一種是Request Body Search
和Request URL Search
方式。Request URL Search
是經過將參數放在URL
以後來達到傳遞查詢語句的目的,好比算法
GET /GET /kibana_sample_data_ecommerce/_search?q=customer_first_name:Eddie
複製代碼
另一種是Request Body Search
是經過將參數以json
串的方式傳遞,相對於Request URL Search
來講更加清晰,更夠傳遞更加複雜的參數。通常在實際的使用中,Request Body Search
會使用的多一些。下面主要講一講Request Body Search
的方式來查詢ElasticSearch
。json
本文使用的數據均爲kibana
中的kibana_sample_data_ecommerce
數據。bash
在ElasticSearch
的查詢API中存在兩種主要的過濾方式。一種是Query
,由query
引導。另一種是filter
,由filter
來引導。二者之間的區別是在query
以後的查詢子句,會對文檔的分數產生影響。而filter
以後的查詢子句不會對文檔的分數產生影響。學習
舉個例子。測試
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"customer_first_name": "Eddie"
}
}
],
"filter": {
"term": {
"customer_full_name.keyword": "Eddie Underwood"
}
}
}
}
}
複製代碼
能夠看到該bool
查詢存在match
和term
子查詢。由於term
在filter
對象內,因此不會對最後的排序分數產生影響。而match
子查詢中的customer_first_name
會對最後的排序分數產生影響。網站
match_all
做爲最簡單的查詢。通常不會在生產環境中使用,在測試環境中使用的會較多。match_all
會查詢出全部的文檔。 舉個例子。搜索引擎
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_all": {}
}
}
複製代碼
今天才發現竟然存在這麼個搜索。match_none
是match_all
的反面,不會搜索到任何的文檔。spa
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_none": {}
}
}
複製代碼
做爲一個全文搜索引擎的意義,對於text
字段使用全文搜索。最典型的應用是能夠用來搜索文章(好比各大博客網站),用來搜索代碼(好比Github)。code
match
查詢是最典型的全文搜索的查詢子句。match
查詢子句會將查詢語句根據字段的分析器分析爲多個單詞。而後逐個查詢文檔中該字段是否存在。 舉個例子。
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match": {
"customer_full_name": "Eddie Weber"
}
}
}
複製代碼
能夠獲得
"hits" : {
"total" : 115,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
}
]
複製代碼
customer_full_name
會被分析爲eddie
和weber
兩個單詞。以後在文檔中的customer_full_name
中查詢是否包含這兩個字段。若是包含了這兩個單詞其中一個,那麼就算是匹配成功。若是一個都沒有包含,那麼就表示匹配不成功。在示例數據中eddie
或者weber
匹配到了115個文檔。
默認狀況下匹配的算法的確跟上面同樣,只要包含了一個單詞就能夠匹配上文檔。可是,也能夠經過參數operator
來修改這個算法。好比下面指定and
操做符。
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match": {
"customer_full_name": {
"query": "Eddie Weber",
"operator": "and"
}
}
}
}
複製代碼
只能匹配上兩個文檔。從原來的匹配115個文檔降到了2個文檔。
"hits" : {
"total" : 2,
"hits" : [
"_source" : {
"customer_full_name" : "Eddie Weber",
複製代碼
這裏表示必須customer_full_name
必須既包含eddie
也要包含weber
才能夠匹配上。
match Phrase
表示短語搜索。當咱們想要搜索一個短語的時候,可使用match Phrase Query
,好比咱們仍是想要搜索customer_full_name
爲Eddie Webber
的人。可是,咱們不想搜索出來只叫作Eddie
,也不想搜索出來叫作Eddie xxx Webber
的人。這個時候可使用match Phrase
,由於match Phrase
不只會要求字段內容中均包含eddie
和webber
也要求這兩個單詞的順序是一致的,中間不能有其餘單詞插入。
好比咱們再插入一條數據,一個叫作Eddie fake Weber
的人。
POST /kibana_sample_data_ecommerce/_doc/1
{
"customer_full_name":"Eddie fake Weber"
}
複製代碼
這個時候,使用match
和and
來進行匹配會發現有三條數據。
"hits" : {
"total" : 3,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name":"Eddie Weber"
},
{
"customer_full_name":"Eddie fake Weber"
}
複製代碼
咱們使用match Phrase Query
來進行搜索。
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase": {
"customer_full_name": "Eddie Weber"
}
}
}
複製代碼
就只會獲得只有名字叫作Eddie Weber
的人。
"hits" : {
"total" : 2,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name" : "Eddie Weber"
}
複製代碼
ElasticSearch
中還提供了一個叫作slop
的參數。使用slop
參數能夠指定單詞之間的最大間隔是多少。間隔指短語中單詞與單詞之間間隔了多少單詞。好比上面的Eddie Weber
中的Eddie
和Weber
沒有間隔任何的單詞,因此間隔爲0。而新插入的數據Eddie fake Weber
中的Eddie
和Weber
間隔爲1,由於間隔了fake
這個單詞。 默認的match phrase
的slop
的值爲0。能夠設置slop
值爲1來匹配上Eddie fake Weber
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase": {
"customer_full_name": {
"query": "Eddie Weber",
"slop": 1
}
}
}
}
複製代碼
能夠匹配上三個文檔。
"hits" : {
"total" : 3,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name":"Eddie Weber"
},
{
"customer_full_name":"Eddie fake Weber"
}
複製代碼
和match
搜索比較下能夠發現match phrase
相似於match
加上and
條件再加上順序和間隔爲0的條件。
match phrase prefix
跟match phrase
之間的區別是match phrase prefix
可讓你在短語的最後一個單詞上進行前綴匹配。好比仍是想要搜索customer_full_name
,這個時候我可能已經忘記了Eddie Weber
的最後一個單詞Weber
的所有內容了。那麼我可使用match phrase prefix
來搜索Eddie We
,由於最後一個單詞We
會進行前綴匹配。因此,我仍是可以搜索到Eddie Weber
這我的。 好比
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase_prefix": {
"customer_full_name": "Eddie We"
}
}
}
複製代碼
能夠匹配上
"hits" : {
"total" : 2,
"max_score" : 9.586426,
"hits" : [
{
"customer_full_name" : "Eddie Weber"
},
{
"customer_full_name" : "Eddie Weber"
}
複製代碼
那麼不是最後一個單詞而是在以前的單詞會進行前綴匹配嗎? 好比我搜索Edd We
GET /kibana_sample_data_ecommerce/_search
{
"query": {
"match_phrase_prefix": {
"customer_full_name": "Edd We"
}
}
}
複製代碼
匹配不上任何的文檔。由於只會對最後一個單詞進行前綴匹配。
"hits" : {
"total" : 0,
"max_score" : null,
"hits" : [ ]
}
複製代碼
另外ElasticSearch
還提供了max_expansions
來控制最後一個前綴單詞和須要匹配的單詞之間的距離。什麼意思?好比上面使用We
來前綴匹配Weber
。那麼這兩個單詞之間的距離是ber
,也就是3個字母的距離。
加入咱們使用max_expansions
來控制匹配的距離爲2,看一下會不會匹配上Weber
?
"百天"寫做計劃下半部。
每週更新一篇碎碎念。
每週3、週六更新一篇儘可能全面,詳細的文章。
可能時長突破了百天,可是又有什麼關係呢?提升寫做水平,造成寫做的習慣纔是最終的目的。
若是這篇文章給你帶來了一些幫助,能夠動動手指點個贊,順便關注一波就更好了。
若是上面都沒有,那麼寫下讀完以後最想說的話?有效的反饋和你的鼓勵是對我最大的幫助。
另外打算把博客給從新撿起來了。歡迎你們來訪問吃西瓜。
我是shane。今天是2019年9月18日。"百天"寫做計劃下半部,52/100。