ElasticSearch 全文搜索引擎

ElasticSearch 全文搜索引擎,第1张

ElasticSearch 全文搜索引擎 一、ElasticSearch 简介 1.什么是 ElasticSearch?

Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。es也使用 Java 开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。

什么是 Lucene?

ES 是在之前的 Lucene 的基础上进行了封装,就像 Mybatis 对 jdbc 进行了封装一样,通过 Restful API,简化了对数据的各种 *** 作

什么是全文检索引擎?

当我们在用 ES 搜索数据的时候,不管数据是什么样的数据,文本也好,word 文档也好,还是页面,都能够被搜索到

2.数据的分类

我们生活中数据总体分为两种:结构化数据与非结构化数据

  1. 结构化数据:指具有固定格式或有限长度的数据,如数据库、元数据等;
  2. 非结构化数据:指不定长或无固定格式的数据,如邮件、word 文档等磁盘上的文件;

结构化数据搜索

常见的结构化数据也就是数据库中的数据,在数据库中所搜很容易实现,通常使用 sql 进行搜索,而且很容易得到查询结果;

为什么数据库搜索很容易?
因为数据库中的数据是有规律的,有行有列,且数据格式、数据长度都是固定的。

非结构化数据搜索

  1. 顺序扫描法

所谓顺序扫描法,就是对磁盘上的所有文件进行顺序扫描,一个文件一个文件的扫描,每个文件都从头扫描到尾,来查询文件中是否有我们需要搜索的内容,这种查询方式相当的慢!!!

  1. 全文检索

首先我们介绍一下索引的概念:

将非结构化数据的中的一部分提取出来,重新组织成有一定结构的数据,然后对此有一定结构的数据进行检索,从而达到搜索相对较快的目的。这部分从非结构数据中提取出来然后重新组织的信息,我们就称之为索引

例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。

这种先建立索引,再对索引进行搜索的过程就叫全文检索

虽然索引的创建非常耗时,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以消耗时间创建索引是值得的。

3.全文检索

我们可以使用 Lucene 实现全文检索。Lucene 是 apache 下的一个开源的全文检索引擎工具包。提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。

而 ES 正是对 Lucene 进行了封装,简化了 *** 作

  1. 全文检索的应用场景
    对于数据量大、数据结构不固定的数据可采用全文检索方式搜索,比如:百度、Google等搜索引擎、论坛站内搜索、电商网站站内搜索等。

  2. 全文检索的实现流程

1、绿色表示索引(建立索引)的过程,对原始内容进行索引建立索引库,索引的过程包括:

  • 确定原始内容:我们要搜索的内容
  • 采集文档
  • 创建文档
  • 分析文档
  • 索引文档

2、红色表示搜索过程,从索引库中搜索内容,搜索包括:

  • 用户通过搜索界面,创建查询(输入关键词)
  • 执行搜索,从索引库中搜索
  • 渲染搜索结果,返回给用户

总之:全文检索分为两个过程:创建索引(Indexing)和搜索索引(Search)


3.1.什么是索引?

文档的索引过程:将用户要搜索的文档内容进行索引,索引存储在索引库(index)中。

那么索引中到底需要存放什么东西呢?

首先我们还是从顺序扫描说起

顺序扫描速度之所以慢,是因为我们不知道每个文件里大致包含哪些东西(关键词),用户输入关键词,我们需要遍历每一个文件,扫描每一个文件才能,返回具有该关键词的文件;

这时我们不妨反过来想,如果我们已经知道了每个文件大致包含了哪些内容(关键词),而且这些关键词都引用了相关的文件,就像 Map 一样,每个 key 都关联了一个或多个 value,这时用户再通过关键词搜索,我们就可以直接给出用户想要的文件;

之后讲到正排索引和倒排索引的时候会更清楚的了解

所以我们要建的索引就是每个文件中包含的大致内容,即关键词

3.2.创建文档对象

获取原始内容的目的就是为了索引,在索引前需要将原始内容创建成文档(document),文档中包括一个一个的域(Field),域中存储内容;

这里的原始内容就是我们想要搜索的一切信息

这里我们可以将磁盘上的一个文件当成一个 document,document 中包括了一些 Field(file_name文件名称、file_path文件路径、file_size文件大小、file_content文件内容)。document 是对原始内容的一个描述对象

注意:每个document可以有多个Field,不同的document可以有不同的Field,同一个document可以有相同的Field(域名和域值都相同)
每个文档都有一个唯一的编号,就是文档id。


3.3.分析文档

上面我们将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析

3.4.创建索引

非结构化数据中所存储的信息是每个文件包含哪些关键词,即已知文件,欲求关键词相对容易,也即是从文件到关键词的映射。【正排索引】

但是对于顺序扫描而言,是用户每次搜索,都要从头到尾遍历一遍,这样在数据量庞大时就会特别慢

而我们想搜索的信息是哪些文件包含此关键词,也即已知关键词,欲求文件,也即从关键词到文件的映射。【倒排索引】

两者恰恰相反。于是如果索引总能够保存从关键词到文件的映射,则会大大提高搜索速度。

强调:我们每一次增删改原始内容的时候,都要重新建立一次索引,当然不一定是立刻就建立索引,我们可以定时建立,每天或每12小时建立一次索引

正排索引:

倒排索引:


说明:

  • “单词ID”一栏记录了每个单词的单词编号;
  • 第二栏是对应的单词;
  • 第三栏即每个单词对应的倒排列表;
  • 比如单词“谷歌”,其单词编号为1,倒排列表为{1,2,3,4,5},说明文档集合中每个文档都包含了这个单词。

强调:倒排列表中还可以存放更多信息来辅助搜索。比如说:我们可以在倒排列表中存储一个关键词在原始内容中出现的次数字段,如下

这样我们就可以通过在关键词出现的频率进行排序

同时我们也可以存储一个文件类型字段(页面,图片…)来辅助我们进行筛选


倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大。

3.5.查询索引

查询索引也是搜索的过程。搜索就是用户输入关键字,从索引库(index)中进行搜索的过程。根据关键字搜索索引,根据索引找到对应的文档,从而找到要搜索的内容(这里指磁盘上的文件)。

3.6.用户查询接口

全文检索系统提供用户搜索的界面供用户提交搜索的关键字,搜索完成展示搜索结果。
比如:



3.7.创建查询

用户输入查询关键字执行搜索之前需要先构建一个查询对象,查询对象中可以指定查询要搜索的 Field 文档域(比如说查询的是页面、图片、word…还是 ppt 等等)、查询关键字等,查询对象会生成具体的查询语法。

3.8.执行查询

搜索索引过程:根据查询语法在倒排索引词典表中分别找出对应搜索词的索引,从而找到索引所链接的文档链表。

3.9.渲染结果

以一个友好的界面将查询结果展示给用户,用户根据搜索结果找自己想要的信息,为了帮助用户很快找到自己的结果,提供了很多展示的效果,比如搜索结果中将关键字高亮显示,百度提供的快照等。


4.Elasticsearch 与 Mysql 的区别 4.1.响应时间
  1. MySQL

背景:当数据库中的文档数仅仅上万条时,关键词查询就比较慢了。如果一旦到企业级的数据,响应速度就会更加不可接受。

原因:在数据库做模糊查询时,如LIKE语句,它会遍历整张表,同时进行字符串匹配。

例如,在数据库查询“手机”时,数据库会在每一条记录去匹配“手机”这两字是否出现。实际上,并不是所有记录都包含“手机”,所以做了很多无用功。这个步骤并不高效,而且随着数据量的增大,消耗的资源和时间都会线性的增长。

  1. Elasticsearch

提升:使用 ES 搜索服务后,这个问题被很好解决,TB 级数据在毫秒级就能返回检索结果。

原因:Elasticsearch 是基于倒排索引的,例子如下。
当搜索“手机”时,Elasticsearch 就会立即返回文档 F,G,H。这样就不用花多余的时间在其他文档上了,因此检索速度得到了数量级的提升。

4.2.分词
  1. MySQL

背景:在做中文搜索时,组合词检索在数据库是很难完成的。

例如:当用户在搜索框输入“四川火锅”时,数据库通常只能把这四个字去进行全部匹配。可是在文本中,可能会出现“推荐四川好吃的火锅”,这时候就没有结果了。

原因:数据库并不支持分词。如果人工去开发分词功能,费时费精力。

  1. Elasticsearch

提升:使用ES搜索服务后,就不用太过于关注分词了,因为 Elasticsearch 支持中文分词插件,很好地解决了问题。

原因:当用户使用 Elasticsearch 时进行搜索时,Elasticsearch 就自动帮他分好词了。

例如 输入“四川火锅”时,Elasticsearch 会自动做下面两件事

  1. 将“四川火锅”分词成“四川”和“火锅”
  2. 查找包含这两个词的文档
4.3.相关性
  1. MySQL

背景:在用数据库做搜索时,结果经常会出现一系列不匹配的文档。比如说:

  1. 没有返回用户想要的文档
  2. 怎么才能把用户想要的文档排序在最前面?

原因:数据库并不支持相关性搜索。

例如:当用户搜索“咖啡厅”的时候,他很可能更想知道附近哪里可以喝咖啡,而不是怎么开咖啡厅。

  1. Elasticsearch

提升:Elasticsearch 能很好地支持相关性评分。通过合理的优化,ES 搜索服务能够返回精准的结果,满足用户的需求。

原因:Elasticsearch 支持全文搜索和相关度评分。这样在返回结果就会根据分数由高到低排列。分数越高,意味着和查询语句越相关。

例如:当用户搜索“星巴克咖啡”,带有“星巴克咖啡”的信息就要比只包含“咖啡”的信息靠前。

  1. 总结
  • 传统数据库在全文检索方面很鸡肋,海量数据下的查询很慢,对非结构化文本数据的不支持,ES 支持非结构化数据的存储和查询。
  • ES 支持分布式文档存储。
  • ES 是分布式实时搜索,并且响应时间比关系型数据库快。
  • ES 在分词方面比关系型好,能做到精确分词。
  • ES 对已有的数据,在数据匹配性方面比关系型数据库好
    例如:搜索“星巴克咖啡”,ES 会优先返回带有“星巴克咖啡”的数据,不会优先返回带有“咖啡”的数据。
  • ElasticSearch 和 MySql 分工不同,MySQL 负责存储数据,ElasticSearch 负责搜索数据。
二、ElasticSearch 安装与启动

下面所有的工具包都在这里
提取码:syhn

1.Windows 版安装

ElasticSearch分为Linux和Window版本
ElasticSearch的官方地址: https://www.elastic.co/products/elasticsearch

说明:ElasticSearch 全版本支持 OpenJDK1.8,如果你的 JDK 不是 1.8 版本,或者不是 OpenJDK 的则需要注意版本兼容

当然我们下载的 ElasticSearch 中包含了一个 jdk ,如果你的 jdk 版本不兼容,可以直接将你 JAVA_HOME 变量改为 ElasticSearch 中的 jdk 目录即可(建议备份原理的 JAVA_HOME,因为你之前的项目都是用的原来的)

安装 ES 服务
Window 版的 ElasticSearch 的安装很简单,解压开即安装完毕,解压后的ElasticSearch的目录结构如下:

安装IK分词器插件:在plugin目录下创建ik文件夹,将 elasticsearch-analysis-ik-7.4.0.zip 内容解压到ik目录下,即可


2.启动 ES 服务

点击 ElasticSearch 下的 bin 目录下的 elasticsearch.bat 启动,控制台显示的日志信息如下:

注意:9300是 tcp 通讯端口,集群间和 TCPClient 都执行该端口,9200 是 http 协议的 RESTful 接口 。
我们通过浏览器访问:http://localhost:9200/,即可

注意事项一:ElasticSearch 是使用 java 开发的,且本版本的 es 需要的 jdk 版本要是 1.8 以上,所以安装 ElasticSearch 之前保证 JDK1.8+ 安装完毕,并正确的配置好 JDK 环境变量,否则启动 ElasticSearch 失败。
注意事项二:出现闪退,通过路径访问发现“空间不足”

修改 conf/jvm.options 文件的22行23行, Elasticsearch 启动的时候占用1个G的内存,可改成 512m:
-Xmx512m:设置 JVM 最大可用内存为 512M。
-Xms512m:设置 JVM 初始内存为 512m。此值可以设置与 -Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存。


3.Postman 安装

省略…这里推荐给大家一个在线的 Postman


4.Kibana客户端(Windows版)

Kibana 是一个针对 Elasticsearch 的开源分析及可视化平台,用来搜索、查看交互存储在 Elasticsearch 索引中的数据。

解压 kibana-7.4.0-windows-x86_64.zip,即可

进入config目录修改kibana.yml第2、28行,配置自身端口和连接的ES服务器地址。把配置打开即可,

server.port: 5601
elasticsearch.hosts: [“http://localhost:9200”]
这里的hosts,填自己的 es 地址,安装在本地就配置 localhost

进入kibana的bin目录,双击kibana.bat启动

访问:http://localhost:5601,即可;

注:这里的界面是英文的,我们可以将 config 下的 yml 配置文件的最后一行 i18n 国际化改为 zh-CN,即可变为中文的;


5.Elasticsearch head 客户端

head插件是ES的一个可视化管理插件,用来监视ES的状态,并通过head客户端和ES服务进行交互,比如创建映射、创建索引等。

将 ElasticSearch-head-Chrome-0.1.5-Crx4Chrome.crx 用压缩工具解压,打开 Chrome 扩展程序,点” 加载已解压的扩展程序”按钮,找到解压目录即可。
或者 直接将 ElasticSearch-head-Chrome-0.1.5-Crx4Chrome.crx 拖到扩展程序窗口也可以

6.IK 分词器的使用

介绍

IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出 了3个大版本。最初,它是以开源项目Lucene为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为 面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

特点

  1. 采用了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的高速处理能力。
  2. 采用了多子处理器分析模式,支持:英文字母(IP地址、Email、URL)、数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇(姓名、地名处理)等分词处理。
  3. 对中英联合支持不是很好,在这方面的处理比较麻烦.需再做一次查询,同时是支持个人词条的优化的词典存储,更小的内存占用。
  4. 支持用户词典扩展定义。
  5. 针对Lucene全文检索优化的查询分析器IKQueryParser;采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。

分词器的三种分词方式:standard、ik_max_word、ik_smart

standard:默认的分词方式,一个字一个词
ik_max_word:会将文本做最细粒度的拆分
ik_smart:做粗粒度的拆分

ik_max_word:
ik_smart:

三、ElasticSearch 相关概念(术语) 1.概述

先说 Elasticsearch 的文件存储,Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档,用 JSON 作为文档序列化的格式,比如下面这条用户数据;

文件存储:一个 ElasticSearch 就是一个用来进行文件存储的服务器

文档型数据库:ElasticSearch 是一个面向文档型数据库软件,一条数据就是一个文档,而在关系型数据库中,一条数据就是一行(关系型数据库中,有行列结构划分)

JSON:上面说的一条数据就是一个文档,其实就是一个 JSON 字符串,ElasticSearch 中存储的都是 JSON 格式的字符串

{
    "name" :     "jack",
    "sex" :      "Male",
    "age" :      25,
    "birthDate": "1990/05/01",
    "about" :    "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

Elasticsearch 可以看成是一个数据库,只是和关系型数据库比起来数据格式和功能不一样而已

  1. 关系型数据库中的一个库 <==> ElasticSearch 中的一个索引(库)
  2. 关系型数据库中的一个表 <==> 就对应 ElasticSearch 中的一个类型。
    例如:在关系型数据库中建立一张 User 表,就相当于在 ElasticSearch 中建立了一个 User 类型,类似于 Java 中的一个Class 类;
  3. 关系型数据库中的一行(一条数据) <==> ElasticSearch 中的一个文档。
    例如关系型数据库中 User 表中的一条记录,就相当于 ElasticSearch 中的一条 JSON 串,类似于 Java 中的一个 Object 实例;
  4. 在数据库中的索引是一个 Tree 结构的树,而在 ElasticSearch 中的索引是一个倒排索引;

2.ElasticSearch 核心概念
  1. 索引(index):文档存储的地方,可以理解为索引【库】,一个数据库;
  2. 类型(type):在 ES6.0 之前有 类型的概念,之后就被抛弃了;
    因为 ES 是全文检索,不关心文档的类型,只要包含关键词的都搜索出来,然后再根据相关性进行排序;
  3. 字段(field):相当于 MySQL 中的字段,在 ES 中可以理解为 JSON 中的键;
  4. 映射(mapping)

映射 是对文档中每个字段的类型进行定义,每一种数据类型都有对应的使用场景。

每个文档都有映射,但是在大多数使用场景中,我们并不需要显示的创建映射,因为ES中实现了动态映射
我们在索引中写入一个下面的 JSON 文档,在动态映射的作用下,name 会映射成 text 类型,age 会映射成 long 类型。

{
    "name":"jack",
    "age":18,
}

自动判断的规则如下:

Elasticsearch中支持的类型如下:

string 类型:在 ElasticSearch 旧版本中使用较多,从 ElasticSearch 5.x 开始不再支持 string,由 text 和 keyword 类型替代。(已经废弃)

text 类型 :Email 内容、产品描述,应该使用 text 类型,text 类型可以被分词。

keyword 类型:比如email地址、主机名、状态码和标签。keyword 类型不支持分词。

示例:

  1. 文档(document)

文档在 ES 中相当于传统数据库中的行的概念,ES 中的数据都以 JSON 的形式来表示,在 MySQL 中插入一行数据和 ES 中插入一个 JSON 文档是一个意思。下面的 JSON 数据表示,一个包含3个字段的文档。

{
    "name":"jack",
    "age":18,
    "gender":1
}

一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是:

节点说明_index文档存储的地方_type文档代表的对象的类_id文档的唯一标识

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5480196.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-12
下一篇2022-12-12

发表评论

登录后才能评论

评论列表(0条)

    保存