ElasticSearch学习随记-整合Springboot版

ElasticSearch学习随记

  • 前言
    • 一、ElasticSearch的安装
    • 二、ElasticSearch的好伙伴-Kibana
    • 三、ElasticSearch常用语法
      • 1.核心概念
        • a)索引 index
        • b)类型 type
        • c)映射 mapping
        • d)字段 field
        • e)文档 document
        • f)路由 routing
    • 四、常用语法规则
      • 1.创建index
      • 2.新增/修改document
      • 3.删除document
      • 4.删除index
      • 5.查询
        • 分词器
        • 分词 analyze
        • 查询 term
        • 查询 terms
        • 查询 match
        • 查询 match_all
        • 查询 multi_match
        • 查询 match_phrase
        • 布尔查询 bool
        • 子句 must
        • 子句 must_not
        • 子句 should
        • 子句 filter
        • sort
    • 五、特殊案例
      • IK分词器
      • 首字母匹配(适用于英文检索)
      • 距离排序
    • 五、如何在Springboot里使用ElasticSearch

前言

本随记内容不足以完全应对ElasticSearch开发环境各种突发情况,只是根据自己的学习进度对日常工作可能遇到的问题的总结与归纳,仅供参考。
PS:以下所提供的各种文档或问题解决思路其实官方文档都有,所以有困难检索官方文档绝对没问题,前提是看得懂英文。

一、ElasticSearch的安装

ElasticSearch的安装网上教程千篇一律,这里就不再进行过多的阐述了。推荐官方民间翻译文档以供参考:

Elasticsearch中文文档 -安装 Elasticsearch

Linux系统里面推荐使用docker进行安装,方便后续维护。在进行docker安装时需要将elasticsearch目录下的config文件夹,data文件夹,plugins文件夹映射到服务器的外部目录下,方便后续的维护和修改。

二、ElasticSearch的好伙伴-Kibana

Kibana是 Elastic 产品集的窗口,可以更方便直观操作命令。你可以把它理解成数据库管理工具Navicat。

Kibana的安装也不进行详细说明,同样贴个几个文档以供参考:

官方文档-安装Kibana
Kibana配置参数概述

三、ElasticSearch常用语法

1.核心概念

a)索引 index

index 类似于传统关系数据库中的一个数据库 ,是一个存储关系型文档的地方。

b)类型 type

每个 index 可以包含多个 type,这里的 type 类似于传统关系数据库中的 表。

c)映射 mapping

mapping 是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等。 所以一个根据实际情况进行合理设计的 mapping 会大大提高查询效率和性能。

d)字段 field

field 相当于是数据表的字段,用于标记区分文档数据不同的属性。

e)文档 document

不同的 type 存储着各自的多个 documentdocument 类似于传统关系数据库中的数据。document 的字段受 mappingfield 的规则限制。

如果新增一个 document 包含了 mapping 不曾定义的一个新的 field ,ElasticSearch会默认在mapping 添加当前属性的 field 信息。虽然这种操作很方便,但是还是建议根据实际情况进行合理的 mapping 构建

f)路由 routing

routing 是一个可变值,默认是 document 的_id,也可以是自定义的值。通过公式 shard = hash(routing) % number_of_primary_shards 可以计算出当前 document 储存在哪个分片上。

四、常用语法规则

ElasticSearch的操作遵循Restful风格,并且数据都是以json格式表示

1.创建index

创建一个名字叫 test_index 的索引
ElasticSearch学习随记-整合Springboot版_第1张图片

index json下有3种属性:

aliases: 索引别名
过滤器和路由
elasticsearch Routing 路由详解

{
  "aliases": {
    "test_index_ali1": {},
    "test_index_ali2": {
    	//过滤器,匹配字段过滤,查询当前别名的文档时,只有匹配的字段才可以查询出来
    	"filter": {},
    	//分配索引储存的路由,保存文档的时候会默认储存在当前分片下
    	"index_routing": "1",
    	//分配索引查询的路由,查询的时候只能查询到当前分片下的文档
    	"search_routing": "1,2",
    	//综合index_routing 和 search_routing的共同用法
    	"routing": "1"
	}
  }
}

mapping: 映射,类似于表结构设计
Elasticsearch 评分score计算中的Boost 和 queryNorm

{
  "mappings": {
    "properties": {
      //字段名
      "title": {
        //字段类型
        "type": "text",
        //分析器
        "analyzer": "ik_smart",
        //评分系数
        "boost": 1
      }
    }
  }
}

setting: 当前索引的配置包括:分片数,副本数,刷新间隔,分析器

{
  "settings":{
   	// 设置索引分片数,默认为1,只能在创建索引时设置,之后任何时候都不能修改
    "number_of_shards": 1,
    // 设置索引分片副本数,默认为1,之后可以任意修改
    "number_of_replicas": 1,
    // 刷新间隔,默认1s
    "refresh_interval": "1s",
    // 分析器
    "analysis":{
    	//分析器
   		"analyzer": {
        	"ngram_analyzer": {
            	"tokenizer": "ngram_tokenizer"
           	}
         },
		 //三者顺序:Character Filters--->Tokenizer--->Token Filter
		 //三者个数:analyzer = CharFilters(0个或多个) + Tokenizer(恰好一个) + TokenFilters(0个或多个)
         //字符过滤器
         "char_filter": {},
         //Token过滤器,将切分的单词进行加工
         "filter": {}, 
         //分词器
         "tokenizer": {}
    }
  }
}

2.新增/修改document

ElasticSearch学习随记-整合Springboot版_第2张图片

3.删除document

在这里插入图片描述

4.删除index

在这里插入图片描述

5.查询

使用ElasticSearch进行数据查询时需要注意以下几点:

  • 受字段类型和分析器的影响,不一定所有的数据都可以查询出来
  • es是适用于一次索引多次查询的场景,如果涉及频繁读写可以根据实际情况提升性能或更换其他技术

分词器

es内置了许多分词器,常用的有:

  • Standard Analyzer - 默认分词器,按词切分,小写处理
  • Simple Analyzer - 按照非字母切分(符号被过滤), 小写处理
  • Stop Analyzer - 小写处理,停用词过滤(the,a,is)
  • Whitespace Analyzer - 按照空格切分,不转小写
  • Keyword Analyzer - 不分词,直接将输入当作输出
  • Patter Analyzer - 正则表达式,默认\W+(非字符分割)
  • Language - 提供了30多种常见语言的分词器
  • Customer Analyzer 自定义分词器
    分词器概念

除此之外,推荐一个第三方的分词器 IK分词器,可以用来切分中文信息。但是除了它配置里面内置的一些词库,有些生僻字或者非常用词语需要自行学习添加,不一定适用所有关键字查询

分词 analyze

如何知道所使用的分词器对需要查询的关键字怎么进行分词的?是否是你想要的结果?可以使用如下查询

GET _analyze
{
 "analyzer": "ik_max_word",
 "text" : "Beauty & Healthy"
}

查询 term

查询某个字段里含有某个关键词的文档,它并不知道分词器的存在,这种查询适合keyword、numeric、date等明确值的
ElasticSearch学习随记-整合Springboot版_第3张图片

查询 terms

查询某个字段里含有多个关键词的文档
ElasticSearch学习随记-整合Springboot版_第4张图片

查询 match

知道分词器的存在,会对field进行分词操作,然后再查询
ElasticSearch学习随记-整合Springboot版_第5张图片

查询 match_all

查询所有文档
ElasticSearch学习随记-整合Springboot版_第6张图片

查询 multi_match

可以指定多个字段
ElasticSearch学习随记-整合Springboot版_第7张图片

查询 match_phrase

ES引擎首先分析查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配短语中的所有分词,并且保证各个分词的相对位置不变
ElasticSearch学习随记-整合Springboot版_第8张图片

布尔查询 bool

Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。
ElasticSearch学习随记-整合Springboot版_第9张图片

子句 must

返回的文档必须满足must子句的条件,并且参与计算分值
ElasticSearch学习随记-整合Springboot版_第10张图片

子句 must_not

返回的文档必须不满足must_not定义的条件。
ElasticSearch学习随记-整合Springboot版_第11张图片

子句 should

返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match参数定义了至少满足几个子句。
ElasticSearch学习随记-整合Springboot版_第12张图片

子句 filter

返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
ElasticSearch学习随记-整合Springboot版_第13张图片

sort

默认排序规则是用es评分倒序排序的,可以自定义其他排序规则。
ElasticSearch学习随记-整合Springboot版_第14张图片

五、特殊案例

IK分词器

IK分词器属于第三方插件,需要自行安装。下载安装包,解压到plugins目录下,重启es即可使用。
IK分词器是根据其内部词库分词的,其内置的词库不一定能完全匹配日常用语,所以可以通过配置文件IKAnalyzer.cfg自行丰富其词库:
ElasticSearch学习随记-整合Springboot版_第15张图片
本地扩展词库修改后需要重启es才能生效;远程词库可以进行热更新。
IK中文分词器远程字典设置+热更新

首字母匹配(适用于英文检索)

中文分词可以用ik分词器解决,但是当查询英文文本进行分词的时候并不能很好命中关键字。举个例子:
现在有个文档name属性的值为Beauty & Healthy,用常规分词器或者ik分词器 使用analyze分析下
ElasticSearch学习随记-整合Springboot版_第16张图片
ElasticSearch学习随记-整合Springboot版_第17张图片
ElasticSearch学习随记-整合Springboot版_第18张图片
可以发现,只有你搜索beauty 或者 healthy 的时候才可以将这条数据查询出来。但有时需要做搜索推荐的时候,可能我们只希望搜索be 或这 b 或者 eau 这种关键字的就能将这条数据带出来,那么已知的常规分词器暂时无法实现这种功能,这个时候就推荐使用edge_ngram 或者 ngram分词器。

这两个分词器需要在创建index的时候去自定义一些常规参数才能正常使用。下面以ngram分词器举例

PUT test_index
{
    "settings": {
    	//NGramTokenizer和NGramTokenFilter的min_gram和max_gram之间允许的最大差异。默认为1。,必须要加,不然会报错
   		"index.max_ngram_diff": 4,
        "analysis": {
          "analyzer": {
          	//声明分词器
            "ngram_analyzer": {
              "tokenizer": "ngram_tokenizer"
            }
          },
          "tokenizer": {
            //定义ngram的参数
            "ngram_tokenizer": {
              "type": "ngram",
              //分词后词语的最小长度
              "min_gram": 1,
              //分词后词语的最大长度
              "max_gram": 4,
              //设置分词的形式,例如,是数字还是文字。elasticsearch将根据分词的形式对文本进行分词。
              "token_chars": [
                "letter",
                "digit"
              ]
            }
          }
        }
      }
}

在这里插入图片描述

返回结果

{
  "tokens" : [
    {
      "token" : "B",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "Be",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "Bea",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "Beau",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "e",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "word",
      "position" : 4
    },
    {
      "token" : "ea",
      "start_offset" : 1,
      "end_offset" : 3,
      "type" : "word",
      "position" : 5
    },
    {
      "token" : "eau",
      "start_offset" : 1,
      "end_offset" : 4,
      "type" : "word",
      "position" : 6
    },
    {
      "token" : "eaut",
      "start_offset" : 1,
      "end_offset" : 5,
      "type" : "word",
      "position" : 7
    },
    {
      "token" : "a",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 8
    },
    {
      "token" : "au",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "word",
      "position" : 9
    },
    {
      "token" : "aut",
      "start_offset" : 2,
      "end_offset" : 5,
      "type" : "word",
      "position" : 10
    },
    {
      "token" : "auty",
      "start_offset" : 2,
      "end_offset" : 6,
      "type" : "word",
      "position" : 11
    },
    {
      "token" : "u",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "word",
      "position" : 12
    },
    {
      "token" : "ut",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "word",
      "position" : 13
    },
    {
      "token" : "uty",
      "start_offset" : 3,
      "end_offset" : 6,
      "type" : "word",
      "position" : 14
    },
    {
      "token" : "t",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "word",
      "position" : 15
    },
    {
      "token" : "ty",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 16
    },
    {
      "token" : "y",
      "start_offset" : 5,
      "end_offset" : 6,
      "type" : "word",
      "position" : 17
    },
    {
      "token" : "H",
      "start_offset" : 9,
      "end_offset" : 10,
      "type" : "word",
      "position" : 18
    },
    {
      "token" : "He",
      "start_offset" : 9,
      "end_offset" : 11,
      "type" : "word",
      "position" : 19
    },
    {
      "token" : "Hea",
      "start_offset" : 9,
      "end_offset" : 12,
      "type" : "word",
      "position" : 20
    },
    {
      "token" : "Heal",
      "start_offset" : 9,
      "end_offset" : 13,
      "type" : "word",
      "position" : 21
    },
    {
      "token" : "e",
      "start_offset" : 10,
      "end_offset" : 11,
      "type" : "word",
      "position" : 22
    },
    {
      "token" : "ea",
      "start_offset" : 10,
      "end_offset" : 12,
      "type" : "word",
      "position" : 23
    },
    {
      "token" : "eal",
      "start_offset" : 10,
      "end_offset" : 13,
      "type" : "word",
      "position" : 24
    },
    {
      "token" : "ealt",
      "start_offset" : 10,
      "end_offset" : 14,
      "type" : "word",
      "position" : 25
    },
    {
      "token" : "a",
      "start_offset" : 11,
      "end_offset" : 12,
      "type" : "word",
      "position" : 26
    },
    {
      "token" : "al",
      "start_offset" : 11,
      "end_offset" : 13,
      "type" : "word",
      "position" : 27
    },
    {
      "token" : "alt",
      "start_offset" : 11,
      "end_offset" : 14,
      "type" : "word",
      "position" : 28
    },
    {
      "token" : "alth",
      "start_offset" : 11,
      "end_offset" : 15,
      "type" : "word",
      "position" : 29
    },
    {
      "token" : "l",
      "start_offset" : 12,
      "end_offset" : 13,
      "type" : "word",
      "position" : 30
    },
    {
      "token" : "lt",
      "start_offset" : 12,
      "end_offset" : 14,
      "type" : "word",
      "position" : 31
    },
    {
      "token" : "lth",
      "start_offset" : 12,
      "end_offset" : 15,
      "type" : "word",
      "position" : 32
    },
    {
      "token" : "lthy",
      "start_offset" : 12,
      "end_offset" : 16,
      "type" : "word",
      "position" : 33
    },
    {
      "token" : "t",
      "start_offset" : 13,
      "end_offset" : 14,
      "type" : "word",
      "position" : 34
    },
    {
      "token" : "th",
      "start_offset" : 13,
      "end_offset" : 15,
      "type" : "word",
      "position" : 35
    },
    {
      "token" : "thy",
      "start_offset" : 13,
      "end_offset" : 16,
      "type" : "word",
      "position" : 36
    },
    {
      "token" : "h",
      "start_offset" : 14,
      "end_offset" : 15,
      "type" : "word",
      "position" : 37
    },
    {
      "token" : "hy",
      "start_offset" : 14,
      "end_offset" : 16,
      "type" : "word",
      "position" : 38
    },
    {
      "token" : "y",
      "start_offset" : 15,
      "end_offset" : 16,
      "type" : "word",
      "position" : 39
    }
  ]
}

Tokenizer常用用法
自定义ngram分词器
edge_ngram 和 ngram的区别

距离排序

常规排序里距离排序占了很大的分量,这里参考官方文档即可。
按距离排序

五、如何在Springboot里使用ElasticSearch

springboot中使用ElasticSearch的详细教程

你可能感兴趣的:(springboot,elasticsearch,elasticsearch,java,搜索引擎)