探索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。

相关文章
相关标签/搜索