探索ElasticSearch-深刻搜索之全文搜索(八)

前言

學習須要先打好基礎,最後才能逐步深刻。今天來從新探索下ElasticSearch的全文搜索。web

搜索

ElasticSearch中存在兩種搜索方式。一種是Request Body SearchRequest 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的方式來查詢ElasticSearchjson

Query and filter context

本文使用的數據均爲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查詢存在matchterm子查詢。由於termfilter對象內,因此不會對最後的排序分數產生影響。而match子查詢中的customer_first_name會對最後的排序分數產生影響。網站

Match All Query

match_all

match_all做爲最簡單的查詢。通常不會在生產環境中使用,在測試環境中使用的會較多。match_all會查詢出全部的文檔。 舉個例子。搜索引擎

GET /kibana_sample_data_ecommerce/_search
{
  "query": {
    "match_all": {}
  }
}
複製代碼

match_none

今天才發現竟然存在這麼個搜索。match_nonematch_all的反面,不會搜索到任何的文檔。spa

GET /kibana_sample_data_ecommerce/_search
{
    "query": {
        "match_none": {}
    }
}
複製代碼

Full text queries

做爲一個全文搜索引擎的意義,對於text字段使用全文搜索。最典型的應用是能夠用來搜索文章(好比各大博客網站),用來搜索代碼(好比Github)。code

match Query

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會被分析爲eddieweber兩個單詞。以後在文檔中的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 Query

match Phrase表示短語搜索。當咱們想要搜索一個短語的時候,可使用match Phrase Query,好比咱們仍是想要搜索customer_full_nameEddie Webber的人。可是,咱們不想搜索出來只叫作Eddie,也不想搜索出來叫作Eddie xxx Webber的人。這個時候可使用match Phrase,由於match Phrase不只會要求字段內容中均包含eddiewebber也要求這兩個單詞的順序是一致的,中間不能有其餘單詞插入。

好比咱們再插入一條數據,一個叫作Eddie fake Weber的人。

POST /kibana_sample_data_ecommerce/_doc/1
{
  "customer_full_name":"Eddie fake Weber"
}
複製代碼

這個時候,使用matchand來進行匹配會發現有三條數據。

"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中的EddieWeber沒有間隔任何的單詞,因此間隔爲0。而新插入的數據Eddie fake Weber中的EddieWeber間隔爲1,由於間隔了fake這個單詞。 默認的match phraseslop的值爲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 Query

match phrase prefixmatch 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。

相關文章
相關標籤/搜索