elasticsearch小白入门

elasticsearch小白入门

介绍

第一次在掘金发表文章,有些不足之处,求勿喷!求勿喷!求勿喷! 身为一个前端,竟然搞es缘由在于咱们公司内部的wiki文档全栈项目的使用,因为日益增多的文章和想要全文检索的需求,而且本来的mongodb数据库,查询全文检索时特别慢,才引入了es。 车300工具平台,项目目前还没公开出来,预计2021年公开。html

起源Lucene

一个叫 Doug Cutting 的美国工程师迷上了搜索引擎,他作了一个用于文本搜索的函数库(软件功能组件),命名为LuceneLuceneJAVA写的,目标是为各类中小型应用软件加入全文检索功能。由于好用且开源,很是受程序员欢迎。 早期是由这我的本身维护,后期作大后,2001年末,成为Apache软件基金会jakarta项目的一个子项目。前端

Lucene 是一个信息检索工具包,jar包,不包含搜索引擎系统! 包含了:索引结构、读写索引的工具、排序、搜索规则...工具类!java

Lucene 和 Elasticsearch

elasticSearch 是基于Lucene 作了一些封装和加强。es是一个开源的、高拓展的、分布式、全文检索引擎。诞生于21世纪大数据时代。(Restful Api)。2016年超过solr,成为排名第一个的搜索引擎类应用。node

Elasticsearch历史

多年前,一个叫作Shay Banon刚结婚不久的失业开发者,因为妻子要去伦敦学习厨师,他就跟老婆一块儿去了,在他找工做的过程当中,为了给妻子构建一个食谱搜索引擎,他就开始使用Lucene工具包开发。因为直接使用原生工具包很是麻烦,因而他就开始抽象化Lucene代码写本身的封装,后来他在找到工做后又重写了 本身的封装,并命名为elasticsearch。 再后来,2010年2月,第一个公开版es发布,es在短期内瞬间成为当时 github 上最受欢迎的项目之一,一家主营es的公司就此成立,他们一边开发新功能,一边提供商用,并永远开源, 遗憾的是,Shay的妻子依然在等待食谱搜索....mysql

什么是搜索?

1)百度,谷歌。咱们能够经过输入一些关键字去搜索咱们须要的东西。 2)互联网的搜索:电商网站。招聘网站。新闻网站。各类APP(百度外卖,美团等等) 3)windows系统的搜索等等linux

总结:搜索无处不在。经过一些关键字,给咱们查询出来跟这些关键字相关的信息git

什么是全文检索?

全文检索是指计算机索引程序经过扫描文章中的每个词,对每个词创建一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先创建的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程相似于经过字典中的检索字表查字的过程。程序员

什么是 Elasticsearch?

使用 java 语言开发的一套开源的全文搜索引擎 用于搜索、日志管理、安全分析、指标分析、业务分析、应用性能监控等多个领域 底层基于 Lucene 开源库开发,提供 restAPI,能够被任何语言调用 支持分布式部署,可水平扩展 更新迭代快、社区活跃、文档丰富(2020年9月写的这篇文章是7.9.1,而如今11月已经7.10.x了)github

自行去官网下载 win linux 及其余版本安装包

连接: elasticsearch下载redis

ik分词器是一个github项目,能够选择git clone 或者 直接download zip

kibana下载

为了方便演示,这边是windows系统下的教程,linux后续推出如何发布线上等等。

熟悉es目录

bin 是启动目录
config 配置文件
--- log4j2 日志配置文件
--- jvm.options java虚拟机相关配置
--- elasticsearch.yml elasticsearch配置文件,默认 9200 端口!
lib 相关jar包
logs 日志
modules 相关模块
plugins 插件如ik
复制代码

启动

直接访问 bin 目录下 elasticsearch.bat

安装可视化插件 elasticsearch-head

git clone https://github.com/mobz/elasticsearch-head.git
复制代码

进入目录后

cnpm install 
复制代码

访问 localhost:9100, 发现跨域问题

去es config目录 的 elasticsearch.yml 添加跨域配置

http.cors.enabled: true 
http.cors.allow-origin: "*" 
复制代码

*表明全部人均可以访问,实际正式环境不能够这样配置

重启 elasticsearch 这时再访问 localhost:9100 便可

kibana的安装与使用

了解 ELK

了解ELK工程师 ELK是 Elasticsearch Logstash Kibana 三大开源库的简称,市面上也称为 Elastic Stack。其中Elasticsearch是一个基于Lucene、分布式、经过Restful方式进行交互的近实时搜索平台框架。像百度、谷歌这种大数据全文搜索引擎的场景均可以使用es这做为底层支持框架,可见es提供的搜索能力确实强大,Logstash 是中央数据流引擎,用于从不一样目标(文件/数据存储/MQ)收集的不一样格式数据,通过过滤后只支持输出到不一样目的地(文件/MQ/redis/es等)。Kibana是一个es可视化工具,提供了实时分析的能力。

收集清洗数据 ---> 搜索,存储 --->Kibana

要保证Kibana版本和es保持一致

kibana的windows下载地址,点击便可下载

启动

kibana-7.9.1-windows-x86_64\bin 目录下的 kibana.bat

|  ![](https://fe.che300.com/easymock/upload/2020/09/22/64a8d5d4abfb5c69f375dc282bdd75fd.png)
|_
复制代码

访问 5601端口便可访问

ps:开发工具!(postman等等其余的)

修改汉化

去配置文件D:\tools\kibana-7.9.1-windows-x86_64\config\kibana.yml中修改

i18n.locale: "zh-CN"
复制代码

es核心概念

es是面向文档的非关系数据库

关系型数据库 es
数据库 索引
types(慢慢被弃用了,7.x.x版本使用统一的_doc,并在查询命令中能够省略)
documents(文档)
字段 fields

文档

es是面向文档的,

  • 意味着索引和搜索数据的最小单位是文档,相似关系数据库中某张表中的一行记录(好理解)
  • 文档会被序列化成 JSON 格式,JSON 对象由字段组成(以json格式存储)
  • 每一个字段都有对应的字段类型,类型能够本身指定,也可使用 ElasticSearch 自动推算(智能化)
  • JSON 文档支持数组和嵌套(自由度很高)
  • 每一个文档都有一个惟一性 ID,能够本身指定,也能够系统自动生成(智能化)

尽管咱们能够随意新增忽略某个字段,可是每一个字段的类型很是重要,好比一个年龄类型字段,能够是字符串也能够是整数,由于es中会保存字段和类型之间的映射以及其余的设置,这种映射具体到每一个映射的每种类型,这也是为何在es中,类型有时候也称为映射类型。

一个文档主要元素大体包含如下内容:

1. _index: 文档所属的索引名
2. _type: 文档所属的类型名(废弃品)
3. _id: 文档的惟一ID
4. _source: 文档存储的 Json 数据
5. _version:文档的版本信息
6. _score: 相关性打分
复制代码

类型

类型是文档的逻辑容器,就像关系型数据库同样,表格是行的容器。

索引

最直接的理解就是数据库!

  • 每一个索引都是一个很是大的文档集合。
  • 每一个索引有本身的 Mapping 用于定义文档的字段名和字段类型
  • 每一个索引有本身的 Settings 用于定义不一样的数据分布,也就是索引使用分片的状况(我没用过👻👻👻)
节点和集群如何工做

一个集群至少有一个节点,而一个节点就是一个es进程,节点能够有多个索引(默认的),若是你建立索引,那么索引将会有5个分片(primary shard,又称主分片)构成的,每个主分片会有一个副本(replica shard,又称复制分片)

由于不是专职作这个的,因此这里关于这些东西就一带而过了。。。,小白入门不须要了解太多底层吧

倒排索引是什么

es使用的是一种称为倒排索引的结构,采用Lucene倒排索引做为底层,这种结构适用于快速的全文索引,一个索引由文档中全部的不重复的列表构成,对于每个词,都有一个包含它的文档列表。例如,如今有两个文档,每一个文档包含以下内容:

Study every day, good good up, to forever # 文档一
To forever, study every day, good good up # 文档二
复制代码

为了建立倒排索引,咱们要将每一个文档拆分红独立的词(词条),而后建立一个包含全部不重复词条的排序列表,而后列出每一个词条出如今哪一个文档

如今咱们要去搜索 to forever 只须要查看包含每一个词条的文档

这里产生了权重!

总结:倒排索引帮咱们彻底过滤掉了一些无用的数据,帮咱们提升了效率

一、索引(数据库) 二、字段类型(mapping) 三、文档 四、分片(了解,Lucene索引)

分词插件(IK分词器)

分词就是把一段中文或者英文划分为一个个关键字,咱们在搜索的时候会把本身的信息进行分词,会把数据库中的或者索引库中的数据进行分词,而后进行一个匹配操做作,默认的中文分词是将每个字当作一个词,好比“我爱育仪”会被分红“我”“爱”“育”“仪”,这里显然是不合理的,因此咱们须要安装中文的分词器。 IK提供了两个分词算法:ik_smartik_max_word,其中 ik_smart是最少切分,ik_max_word是最细粒度划分!

附件中有IK分词器的安装包 一、安装 二、直接解压到es安装目录的plugin目录中命名为ik 三、重启es

验证 分词器是否安装完成, 四、使用 elasticsearch-plugin

五、用kibana测试!

ik_smart 最少划分

ik_max_word 最多划分

两种分词器使用的最佳实践是:索引时用ik_max_word,在搜索时用ik_smart。 即:索引时最大化的将文章内容分词,搜索时更精确的搜索到想要的结果。

一、ik_max_word

会将文本作最细粒度的拆分,好比会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。

二、ik_smart 会作最粗粒度的拆分,好比会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。

发现问题

这种本身须要的词,须要咱们本身加上咱们的分词器中,才会实现真正的分词

本身添加词典

D:\tools\elasticsearch-7.9.1\plugins\ik\config\IKAnalyzer.cfg.xml(这是个人路径,别人和我不同的) 在这个目录下修改

|  ![](https://fe.che300.com/easymock/upload/2020/09/22/94b72e0a58ac77eec8dc4ae38da4b2e2.png)
|_
复制代码

elasticsearch-7.9.1\plugins\ik\config 目录下新建 自定义的词典例如: 一、新建yuyi.dic 二、在 该文件中写入 三、在下图位置加上本身的配置文件名 四、重启es 五、再次测试

GET _analyze
{
  "analyzer": "ik_smart",
  "text": "超级喜欢育仪讲"
}
复制代码

返回值发生了变化

{
  "tokens" : [
    {
      "token" : "超级",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "CN_WORD",
      "position" : 0
    },
    {
      "token" : "喜欢",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "育仪",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "讲",
      "start_offset" : 6,
      "end_offset" : 7,
      "type" : "CN_CHAR",
      "position" : 3
    }
  ]
}
复制代码

之后须要本身配置,就须要本身在分词中设置便可

Rest 风格说明

这是一种架构风格而不是标准,他用于客户端与服务器交互 类的软件,基于这个风格设计软件能够更简洁、更有层次等。

method url地址 描述
PUT localhost:9200/索引名称/类型名称/文档id 建立文档(指定文档id)
POST localhost:9200/索引名称/类型名称 建立文档(随机文档id)
POST localhost:9200/索引名称/_update/文档id 修改文档
DELETE localhost:9200/索引名称/类型名称/文档id 删除文档
GET localhost:9200/索引名称/类型名称/文档id 经过文档id查询文档
POST localhost:9200/索引名称/类型名称/_search 查询全部数据

建立文档

示例1
PUT /test1/type1/1
{
  "name":"育仪",
  "age":24
}
复制代码

类型名将来在 8版本中会被删除

示例2
PUT /test3/_doc/1
{
  "name":"育仪分享会",
  "age":24,
  "birth":"1996-09-12"
}
复制代码

这里的_doc是将来es官方指定的类型,将来将去掉类型名称,统一为一个系统指定的_doc

若是咱们没有指定 文档类型,es默认会帮咱们指定类型

字段指定类型

  • 字符串类型:text、keyword
  • 数值类型:long、integer、short、byte、double、float、half float、scaled float
  • 日期类型:date
  • te布尔类型:boolean
  • 二进制类型:binary
  • 等等......

测试

PUT /test2
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "long"
      },
      "birthday":{
        "type": "date"
      }
    }
  }
}
复制代码

返回上图则成功

mappings、properties为指定字段类型的必须格式,内部的name、age、birthday为用户想要的类型,相似mysql的建表。

经过get请求获取信息

GET /test2
复制代码

能够经过get请求,直接获取test2索引的所有信息

拓展:经过命令 查看 es 索引状况

查看数据库健康值

GET _cat/health
复制代码

查看es不少信息

GET _cat/indices?v
复制代码

等等还有不少

修改

修改提交仍是使用PUT 而后覆盖便可!(曾经的方法)

PUT /test3/_doc/1
{
  "name":"育仪分享会20200921",
  "age":24,
  "birth":"1996-09-12"
}
复制代码

这种修改更新方式是总体修改,一旦丢掉数据则会产生修改错误的字段

更新的方法(新的)

POST /test3/_update/1
{
  "doc":{
    "name":"育仪大魔王"
  }
}
复制代码

更新成功,再调用查看方法便可发现就name字段发生了变化。 值得注意的是 doc是固定写法

删除

删除整个索引

DELETE /test1
复制代码

返回值:

删除一条数据

Delete /test3/_doc/1
复制代码

使用RESTFUL风格是咱们ES推荐你们使用的!

关于文档的操做

基本操做

一、先建立一个索引并加入数据

PUT /yuyi/_doc/1
{
  "name":"朱育仪",
  "age":24,
  "desc":"我明天就要分享了,我慌的一批",
  "tags":["技术宅","温暖","直男"]
}

PUT /yuyi/_doc/2
{
  "name":"张三",
  "age":24,
  "desc":"我是张三",
  "tags":["傻叉","旅游","渣男"]
}

PUT /yuyi/_doc/3
{
  "name":"李四",
  "age":30,
  "desc":"我是李四",
  "tags":["靓女","旅游","唱歌"]
}
复制代码

二、查询 查询yuyi索引下的 1号人物

GET /yuyi/_doc/1
复制代码

三、搜索 条件查询 获取一号用户的

GET /yuyi/_doc/_search?q=name:朱育仪
复制代码

咱们发现 上图中有一个 _score这个字段,若是有多条数据,匹配度越高则分值越高

略复杂的查询方式

GET /yuyi/_doc/_search
{
  "query":{
    "match":{
      "name":"朱育仪"
    }
  }
}
复制代码

仍是同样返回上文图片的返回值

经过 _source 指定返回值

GET /yuyi/_doc/_search
{
  "query":{
    "match":{
      "name":"朱育仪"
    }
  },
  "_source":["name","age"]
}
复制代码

![]

咱们以后使用nodejs 操做es,全部的方法和对象就是这里面的key!

排序

GET /yuyi/_doc/_search
{
  "query":{
    "match_all":{}
  },
  "sort":[
    {
      "age":{
        "order":"desc"
      }
    }
  ]
}
复制代码

match_all表明全文匹配 sort 字段是个数组里面传递对象用来排序,上面的语句是对age进行排序,order表明排序规则“desc降序 asc升序” 有了固定的排序后,_score分值就没了。

分页

GET /yuyi/_doc/_search
{
  "query":{
    "match_all":{
    }
  },
  "sort":[
    {
      "age":{
        "order":"desc"
      }
    }
  ],
  "from":0,
  "size":2
}
复制代码

from表明了从第几个开始,size表示每页多少个

布尔值查询

GET /yuyi/_doc/_search
{
  "query":{
    "bool":{
      "must":[
        {
          "match":{
            "name":"育仪"
          }
        },
        {
          "match":{
            "age":24
          }
        }
      ]
    }
  }
}
复制代码

采用 bool字段, 内部可选参数:must(必须包含)must_not(必须不包含)should(有一个就能够了)(minimum_should_match: 用来控制至少匹配多少个should匹配的) 上面匹配的是 name包含 育仪字段 age24的数据

should查询测试

GET /yuyi/_doc/_search
{
  "query":{
    "bool":{
      "should":[
        {
          "match":{
            "name":"育仪"
          }
        },
        {
          "match":{
            "age":24
          }
        }
      ]
    }
  },
  "from":0,
  "size":2
}
复制代码

会返回只要符合name 是育仪 或者 age是 24的就能够了。

过滤查询

GET /yuyi/_doc/_search
{
  "query":{
    "bool":{
      "must":[
        {
          "match":{
            "name":"育仪"
          }
        }
      ],
      "filter":{
        "range":{
          "age":{
            "gte":10,
            "lte":30
          }
        }
      }
    }
  }
}
复制代码

经过 filter查询过滤数据,将过滤age大于等于10小于等于30的 gt大于 lt小于 gte大于等于 lte小于等于

数组类型也能够匹配

GET /yuyi/_doc/_search
{
  "query":{
    "match":{
      "tags":"男"
    }
  }
}
复制代码

想要匹配多个条件直接空格隔开便可

GET /yuyi/_doc/_search
{
  "query":{
    "match":{
      "tags":"男 技术"
    }
  }
}
复制代码

咱们发现只要匹配到了这两个词中的任意一个,就会被返回,然而第二条数据并不太符合技术这个关键词。 这个时候能够经过返回值中的分值进行基本的判断,匹配程度。

精确查询

term 直接经过倒排索引精确查找的

关于分词,term会直接查询精确值,match会使用分词器解析,再经过分析的文档查询

两个类型 text keyword text类型会被分词器进行解析 keyword不会被分割解析

测试代码一个一个请求

PUT testdb
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "desc":{
        "type": "keyword"
      }
    }
  }
}

PUT testdb/_doc/1
{
  "name":"育仪准备分享会",
  "desc":"育仪准备分享会"
}

PUT testdb/_doc/2
{
  "name":"育仪准备分享会 name",
  "desc":"育仪准备分享会 desc"
}
复制代码

查看分词结果

GET _analyze
{
  "analyzer": "keyword",
  "text":"育仪准备分享会"
}
复制代码

如上图所示,keyword形式将再也不进行分词

GET _analyze
{
  "analyzer": "ik_smart",
  "text":"育仪准备分享会"
}
复制代码

使用ik分词器后是这个结果

精准查询的测试

GET /testdb/_search
{
  "query":{
    "term":{
      "name":"育"
    }
  }
}
复制代码

查询name中含有的数据,因为name属性是text类型,会被分词

GET /testdb/_search
{
  "query":{
    "term":{
      "desc":"育"
    }
  }
}
复制代码

此时咱们发现 desc查询字时无值,因为咱们使用了keyword类型 ,因此咱们必须使用育仪准备分享会 所有文字才能匹配到值。以下方的测试

GET /testdb/_search
{
  "query":{
    "term":{
      "desc":"育仪准备分享会"
    }
  }
}
复制代码

总结:keyword不会被分词器解析

多个值匹配的精确查询

测试代码(插入多个数据)

PUT testdb/_doc/3
{
  "t1":"22",
  "t2":"2020-09-23"
}
PUT testdb/_doc/4
{
  "t1":"33",
  "t2":"2020-09-24"
}
复制代码

使用 term精确查询多个值

GET /testdb/_search
{
  "query":{
    "bool":{
      "should": [
        {
          "term":{
            "t1":"22"
          }
        },
        {
          "term":{
            "t1":"33"
          }
        }
      ]
    }
  }
}
复制代码

高亮查询

GET /yuyi/_search
{
  "query":{
    "match":{
      "name":"育仪"
    }
  },
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}
复制代码

经过 上文方式能够实现高亮,highlight``fields为固定写法

咱们这里不想用em标签 想用其余的

GET /yuyi/_search
{
  "query":{
    "match":{
      "name":"育仪"
    }
  },
  "highlight": {
    "pre_tags": "<p class='myClassName' style='color:red'>", 
    "post_tags": "</p>", 
    "fields": {
      "name": {}
    }
  }
}
复制代码

这里使用 pre_tags post_tags 来自定义标签高亮

参考文档:

Elasticsearch 集群分配多少分片合理

RESTful API接口设计标准及规范

Elasticsearch的停用词

Elasticsearch 之(24)IK分词器配置文件讲解以及自定义词库

ElasticSearch 9200和9300端口的做用

为何如今要移除type?

Elasticsearch 入门学习

ik_max_word和 ik_smart介绍

还有不少借鉴其余的出处忘记了。。。

相关文章
相关标签/搜索