1. 测试数据准备

官方GitHub有给我们提供测试数据,https://github.com/elastic/elasticsearch/edit/master/docs/src/test/resources/accounts.json

进入,将数据复制,然后在Kibana上执行批量操作,如图:

es全文检索 分词策略 es如何实现全文检索_elasticsearch

查看索引信息

es全文检索 分词策略 es如何实现全文检索_es全文检索 分词策略_02

API官网参考地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html

以下内容均可在上面API官网参考地址中找到出处 

2. Search API

        ES支持两种基本检索方式:

1)通过使用Rest request url 发送搜索参数(uri + 检索参数)

2)通过REST request body 来发送它们(uri + 请求体)

2.1 检索信息

一切检索从 _search 开始

GET  bank/_search

检索 bank 下所有的信息,包括type和docs

GET bank/_search?q=*&sort=account_number:asc

请求参数方式检索

响应结果解释:

took:ElasticSearch执行搜索的时间,单位毫秒

timed_out:搜索是否超时

_shards:告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片

hits:搜索结果

hits.total:搜索结果

hits.hits:实际的搜索结果数组(默认为前10的文档)

sort:搜索结果的排序key(键)(没有则按照score排序)

score和max_score:相关性得分和最高分(全文检索用)

2.1.1 检索所有

例如:

GET bank/_search

es全文检索 分词策略 es如何实现全文检索_elasticsearch_03

2.1.2 请求参数方式检索

例如:

GET bank/_search?q=*&sort=account_number:asc

es全文检索 分词策略 es如何实现全文检索_字段_04

参数解释:

GET:表示发送get请求

bank:表示索引

_search:固定写法

q=* :表示查询所有

sort=account_number:asc:表示查询结果按照account_number字段升序排序

2.2 uri + 请求体检索

例如:

GET bank/_search
{
    "query":{
      "match_all":{}
    },
    "sort":[
        {
            "account_number":{
                "order":"desc"
            }
        }
    ]
}

参数解释:

1) GET bank/_search:表示get请求bank索引下的数据

2)query:表示查询条件,match_all表示匹配所有,规则有就写,没有就写一个大括号{}

3)sort:表示排序规则,上面写法也可以改成如下形式

GET bank/_search
{
    "query":{
      "match_all":{}
    },
    "sort":[
        {
            "account_number":"desc"
        }
    ]
}

es全文检索 分词策略 es如何实现全文检索_elasticsearch_05

搜索结果如图:

es全文检索 分词策略 es如何实现全文检索_es全文检索 分词策略_06

注意:postman中,get请求不能携带请求体,我们可以将get请求改成一个json风格的post查询请求体到 _search API。一旦搜索的结果被返回,ElasticSearch就完成了这次请求,并且不会维护任何服务端的资源或者结果的cursor(游标)

3. Query DSL

语法参考地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html

3.1 基本语法格式

        ElasticSearch提供了一个可以执行查询的json风格的DSL(domain-specific language 领域特定语言)。这个被称之为Query DSL。该查询语言非常全面,并且刚开始的时候感觉有点复杂,之后我们的查询几乎都是使用该种方式进行

例如:上面的 uri + 请求体检索 就是一个Query DSL查询

3.1.1 典型语法解构

{
    QUERY_NAME:{
        ARGUMENT:VALUE,
        ARGUMENT:VALUE, ... ...
    }
}

3.1.2 针对具体字段的查询

{
    QUERY_NAME:{
        FIELD_NAME:{
            ARGUMENT:VALUE,
            ARGUMENT:VALUE,
            
        }
    }
}

3.2 常见的argument

1)query:定义如何查询

2)match_all:查询类型,代表查询所有。

注意:es中可以在query中组合非常多的查询类型完成复杂查询

3)form + size 限定,可以完成分页查询功能

4)sort:排序。多个字段排序,会在前序字段相等时,后续字段内部排序,否则以前序为准

5)_source:指定需要返回的字段

例如:

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 3,
  "sort": [
    {
      "account_number": "desc"
    }
  ],
  "_source": "firstname"
}

注意:如果要返回多个字段,需要用数组,如图:

es全文检索 分词策略 es如何实现全文检索_全文检索_07

返回结果如图:

es全文检索 分词策略 es如何实现全文检索_字段_08

3.3 match 全文检索匹配查询

        前面我们在query中使用了match_all来查询所有,现在我们使用math来查询指定的值。

        全文检索按照评分进行排序,会对检索条件进行分词匹配,并计算匹配结果得分_score

语法:

GET bank/_search
{
  "query":{
    "match": {
      "FIELD": "TEXT"
    }
  }
}

3.3.1 基本类型(非字符串),精确匹配

匹配account_number=20的用户

GET bank/_search
{
  "query":{
    "match": {
      "account_number": "20"
    }
  }
}

搜索结果如图:

es全文检索 分词策略 es如何实现全文检索_elasticsearch_09

3.3.2 字符串,全文检索

1)查询出address中包含Kings的所有记录

GET bank/_search
{
  "query":{
    "match": {
      "address": "Kings"
    }
  }
}

搜索结果如图:

es全文检索 分词策略 es如何实现全文检索_全文检索_10

match当搜索字符串类型的时候,会进行全文检索,并且每条记录都要相关性得分

2)字符串,多个单词(分词+全文检索)

GET bank/_search
{
  "query":{
    "match": {
      "address": "mill road"
    }
  }
}

如图:

es全文检索 分词策略 es如何实现全文检索_全文检索_11

 最终查询出address中包含mill或者road或者mill road的所有记录,并给出相关性得分

3.4 match_phrase短语匹配

将需要匹配的值当成一个整体单词(不分词)进行检索

语法:

GET bank/_search
{
  "query":{
    "match_phrase": {
      "FIELD": "PHRASE"
    }
  }
}

例如:查询address中包含mill road的所有记录,并给出相关性得分

GET bank/_search
{
  "query":{
    "match_phrase": {
      "address": "mill road"
    }
  }
}

es全文检索 分词策略 es如何实现全文检索_字段_12

短语匹配也可以使用match+keyword关键字查询

例如;

GET bank/_search
{
  "query":{
    "match": {
      "address.keyword": "990 Mill Road"
    }
  }
}

查询结果:

es全文检索 分词策略 es如何实现全文检索_字段_13

 注意:match+keyword与match_phrase短语匹配的区别是,match_phrase短语匹配可以匹配包含关系,但是match+keyword只能全包也就是精确查询,例如上面的例子,将"990 Mill Road"替换成"Mill Road"使用match+keyword就匹配不到

3.5 multi_match多字段匹配

语法:

GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "",
      "fields": []
    }
  }
}

例如:查询state和address中包含mill的用户

GET bank/_search
{
  "query":{
    "multi_match": {
      "query": "mill",
      "fields": ["state","address"]
    }
  }
}

结果如图:

es全文检索 分词策略 es如何实现全文检索_搜索_14

注意:如果query查询内容包含多个单词,也会进行分词

3.6 bool复合查询

bool复合查询有四个条件值可供组装 must、must_not、should、filter

3.6.1 must/must_not

必须是与必须不是指定的情况

例如1:查询age=38且lastname=Small的用户

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "age": "38"
          }
        },
        {
          "match": {
            "lastname": "Small"
          }
        }
      ]
    }
  }
}

查询结果:

es全文检索 分词策略 es如何实现全文检索_全文检索_15

例如2:查询age=38且lastname=Small,且firstname不等于White的用户

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "age": "38"
          }
        },
        {
          "match": {
            "lastname": "Small"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "firstname": "White"
          }
        }
      ]
    }
  }
}

es全文检索 分词策略 es如何实现全文检索_搜索_16

例如3:查询年龄在18-30之间的用户

 使用range

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "age": {
              "gte": 18,
              "lte": 30
            }
          }
        }
      ]
    }
  }
}

查询结果如图:

es全文检索 分词策略 es如何实现全文检索_es全文检索 分词策略_17

3.6.2 should

        应该达到should列举的条件,如果达到会增加相文档的评分,并不会改变查询结果。如果query只有should且只有一种匹配规则,那么should的条件就会被视作默认匹配条件而去改变查询结果

例如:查询年龄必须等于38且地址必须包含mill并且firstname应该=Parker的用户

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "age": "38"
          }
        },
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "should": [
        {
          "match": {
            "firstname": "Parker"
          }
        }
      ]
    }
  }
}

查询结果;

es全文检索 分词策略 es如何实现全文检索_es全文检索 分词策略_18

可以发现,当满足should的条件的时候,相关性得分就比较高

3.6.3 filter结果过滤

并不是所有的查询都需要产生分数,特别是那些仅用于filtering(过滤)的文档,为了不计算分数,ES会自动检查场景并且优化查询的执行,也就是使用filter检索,不会贡献相关性得分。

注意:must_not是一种filter,所以must_not的匹配也不会贡献相关性得分

例如:使用filter代替must查询age在18-30之间的用户

GET /bank/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "age": {
              "gte": 18,
              "lte": 30
            }
          }
        }
      ]
    }
  }
}

查询结果如图,相关性得分都为0.0,证明filter检索不贡献文档相关性得分

es全文检索 分词策略 es如何实现全文检索_es全文检索 分词策略_19

3.7 term

        和match一样,匹配某个属性的值,全文检索字段用match,其他非text字段匹配用term,也就是term适用于精确匹配

例如;查询年龄=28的用户

GET /bank/_search
{
  "query": {
    "term": {
      "age": 28
    }
  }
}

查询结果如图;

es全文检索 分词策略 es如何实现全文检索_搜索_20

3.8 嵌入式属性查询nested

嵌入式的属性其心态类似于List<Attrs> attrs这样的格式的,在es中存储的格式如下图所示:

es全文检索 分词策略 es如何实现全文检索_搜索_21

该格式的数据,无法通过普通的查询来获取到查询结果因为es会对嵌入式的数据进行扁平化处理,如:

es全文检索 分词策略 es如何实现全文检索_es全文检索 分词策略_22

3.8.1 语法格式

详情参看官网介绍:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-nested-query.html

1)存储语法格式

PUT /my_index
{
    "mappings" : {
        "properties" : {
            "obj1" : {
                "type" : "nested"
            }
        }
    }
}

2)查询语法格式

GET /my_index/_search
{
    "query":  {
        "nested" : {
            "path" : "obj1",
            "query" : {
                "bool" : {
                    "must" : [
                    { "match" : {"obj1.name" : "blue"} },
                    { "range" : {"obj1.count" : {"gt" : 5}} }
                    ]
                }
            },
            "score_mode" : "avg"
        }
    }
}

注意:

1)path就是嵌入式属性的名称,如图:

es全文检索 分词策略 es如何实现全文检索_字段_23

2) 查询语法也可以写在filter中,一般对于不需要评分的字段查询都写在filter中,可以提高查询效率。

例如:

GET product/_search
{
  "query": {
    "bool": {
      "filter": {
        "nested": {
          "path": "attrs",
          "query": {
            "bool": {
              "must": [
                {
                  "term": {
                    "attrs.attrId": {
                      "value": "15"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

查询结果如下:

es全文检索 分词策略 es如何实现全文检索_elasticsearch_24