全文搜索之 Elasticsearch

时间:2022-08-27 09:50:17

概述

Elasticsearch (ES)是一个基于 Lucene 的开源搜索引擎,它不但稳定、可靠、快速,而且也具有良好的水平扩展能力,是专门为分布式环境设计的。

特性

  • 安装方便:没有其他依赖,下载后安装非常方便;只用修改几个参数就可以搭建起来一个集群
  • JSON:输入/输出格式为 JSON,意味着不需要定义 Schema,快捷方便
  • RESTful:基本所有操作(索引、查询、甚至是配置)都可以通过 HTTP 接口进行
  • 分布式:节点对外表现对等(每个节点都可以用来做入口);加入节点自动均衡
  • 多租户:可根据不同的用途分索引;可以同时操作多个索引

集群

其中一个节点就是一个 ES 进程,多个节点组成一个集群。一般每个节点都运行在不同的操作系统上,配置好集群相关参数后 ES 会自动组成集群(节点发现方式也可以配置)。集群内部通过 ES 的选主算法选出主节点(目前版本 1.2 存在脑裂问题),而集群外部则是可以通过任何节点进行操作,无主从节点之分(对外表现对等/去中心化,有利于客户端编程,例如故障重连)。

索引

“索引”有两个意思:

  • 作为动词,它指的是把一个文档“保存”到 ES 中的过程,索引一个文档后,我们就可以使用 ES 搜索到这个文档
  • 作为名词,它是指保存文档的地方,相当于一个数据库概念中的“库”

为了方便理解,我们可以将 ES 中的一些概念对应到我们熟悉的关系型数据库上:

    ES         索引         类型         文档    
    DB         库          表     行

分片

ES 是一个分布式系统,我们一开始就应该以集群的方式来使用它。它保存索引时会选择适合的“分片”(Primary Shard),把索引保存到其中(我们可以把分片理解为一块物理存储区域)。分片的分法是固定的,而且是安装时候就必须要决定好的(默认是 5),后面就不能改变了。

既然有主分片,那肯定是有“从”分片的,在 ES 里称之为“副本分片”(Replica Shard)。副本分片主要有两个作用:

  • 高可用:某分片节点挂了的话可走其他副本分片节点,节点恢复后上面的分片数据可通过其他节点恢复
  • 负载均衡:ES 会自动根据负载情况控制搜索路由,副本分片可以将负载均摊

一个示例

来个示例总结一下上面的内容(结合下面的图一起看):

  • 3 个 ES 节点(es-58/59/60)组成一个集群
  • 搭建集群时使用默认的主分片数 5,shard0~shard4
  • 该集群内有加入两个索引 index1、index2
  • 这两个索引中分别“索引”(保存)了两个文档
  • index1 索引中这个文档被 ES 自动保存到了分片 2 中,主分片在 es-58 节点,副本分片在 es-59 节点
  • index2 索引中这个文档被 ES 自动保存到了分片 2 中,主分片在 es-59 节点,副本分片在 es-58 节点

全文搜索之 Elasticsearch

(该图是使用 ES 的 RESTful 接口获取的,后面会介绍常用接口)

多租户

ES 的多租户简单的说就是通过多索引机制同时提供给多种业务使用,每种业务使用一个索引(关于多租户的详细定义与用途,可以参考这里)。前面我们提到过可以把索引理解为关系型数据库里的库,那多索引可以理解为一个数据库系统建立多个库给不同的业务使用。

在实际使用时,我们可以通过每个租户一个索引的方式将他们的数据进行隔离,并且每个索引是可以单独配置参数的(可对特定租户进行调优),这在典型的多租户场景下非常有用:例如我们的一个多租户应用需要提供搜索支持,这时可以通过 ES 根据租户建立索引,这样每个租户就可以在自己的索引下搜索相关内容了。

RESTful

这个特性非常方便,最关键的是 ES 的 HTTP 接口不只是可以进行业务操作(索引/搜索),还可以进行配置,甚至是关闭 ES 集群。下面我们介绍几个很常用的接口:

  • /_cat/nodes?v:查集群状态
  • /_cat/shards?v:查看分片状态
  • /${index}/${type}/_search:搜索

v 是 verbose 的意思,这样可以更可读(有表头,有对齐),_cat 是监测相关的 APIs,/_cat?help 来获取所有接口。${index} 和 ${type} 分别是具体的某一索引某一类型,是分层次的。我们也可以直接在所有索引所有类型上进行搜索:/_search。

官方术语表

最后,来份官方的术语表翻译,巩固一下理解:

analysis 分析

分析是将文本(text)转化为查询词(term)的过程。使用不同的分析器,这三种短语:FOO BAR,Foo-Bar,foo,bar 都有可能被分解成查询词 foo 与 bar。这些查询词实际上将被存储在索引中。一次对 FoO:bAR 的全文查询(不是查询词查询)可能会被分析为为查询词 foo,bar,可以匹配上保存在索引中的查询词。这就是分析处理过程(包含了索引与搜索),它使得 es 可以进行全文查询。

cluster 集群

一个或多个拥有同一个集群名称的节点组成了一个集群。每个集群都会自动选出一个主节点,如果该主节点故障,则集群会自动选出新的主节点来替换故障节点。

document 文档

一个文档就是一个保存在 es 中的 JSON 文本,可以把它理解为关系型数据库表中的一行。每个文档都是保存在索引中的,拥有一种类型和 id。一个文档是一个 JSON 对象(一些语言中的 hash / hashmap / associative array)包含了 0 或多个字段(键值对)。原始的 JSON 文本在索引后将被保存在_source 字段里,搜索完成后返回值中默认是包含该字段的。

id

Id 是用于标识文档的,一个文档的索引/类型/id 必须是唯一的。文档 id 是自动生成的(如果不指定)。

field 字段

一个文档包含了若干字段,或称之为键值对。字段的值可以是简单(标量)值(例如字符串、整型、日期),也可以是嵌套结构,例如数组或对象。一个字段类似于关系型数据库表中的一列。每个字段的映射都有一个字段类型(不要和文档类型搞混了),它描述了这个字段可以保存的值类型,例如整型、字符串、对象。映射还可以让我们定义一个字段的值如何进行分析。

index 索引

一个索引类似关系型数据库中的一个数据库,它可以映射为多种类型。一个索引就是逻辑上的一个命名空间,对应到 1 或多个主分片上,可以拥有 0 个或多个副本分片。

mapping 映射

一个映射类似于关系型数据库中的模式定义。每个索引都存在一个映射,它定义了该索引中的每一种类型,以及索引相关的配置。映射可以显示定义,或者在文档被索引时自动创建。

node 节点

一个节点是集群中的一个 es 运行实例。测试时,多个节点可以同时启在同一个服务器上,生产环境一般是一个服务器上一个节点。节点启动时将使用单播(或者是组播)来发现和自己配置的集群名称相同的集群,并尝试加入到该集群中。

primary shard 主分片

每个文档都会被保存在一个主分片上。当我们索引一个文档时,它将在一个主分片上进行索引,然后才放到该主分片的各副本分片上。默认情况下,一个索引有 5 个主分片。我们可以指定更少或更多的主分片来伸缩索引可处理的文档数。需要注意的是,一旦索引创建,就不能修改主分片个数。

replica shard 副本分片

每个主分片可以拥有 0 个或多个副本分片。一个副本分片是主分片的一份拷贝,这样做有两个主要原因:

  1. 故障转移:当主分片失效时,一个副本分片会被提升为主分片
  2. 提高性能:获取与搜索请求可以被主分片或副本分片处理。默认情况下,每个主分片都有一个副本分片,副本分片的数量可以动态调整。在同一个节点上,副本分片和其主分片不会同时运行

routing 路由

当我们索引一个文档时,它将被保存在一个主分片上,分片的选择是通过路由值哈希得到的。默认情况下,路由值来自于文档 id,如果该文档指定来了父文档,则路由值来自于父文档 id(这是为了确保子文档和父文档被保存在相同的分片上)。该值可以在索引时指定,也可以通过映射路由字段来指定。

shard 分片

一个分片就是一个 Lucene 实例,它是 es 管理的底层“工作单元”。一个索引是逻辑上的一个命名空间,指向主分片和副本分片。索引的主分片和副本分片数量必须明确指定好,在应用代码使用时只需要处理和索引的交互,不会涉及到和分片的交互。Elasticsearch 会在集群中的所有节点上设置好分片,但节点失效或加入新节点时会自动将移动节点分片。

source field 源字段

默认情况下,在获取和搜索请求返回值中的 _source 字段保存了源 JSON 文本,这使得我们可以直接在返回结果中访问源数据,而不需要根据 id 再发一次检索请求。注意:索引的 JSON 字符串将完整返回,无论是否是一个合法的 JSON。该字段的内容也不会描述数据如何被索引。

term 查询词

一个查询词是一个被 es 索引的确切值。查询词 foo,Foo,FOO 是不同的。查询词可以使用查询词查询接口进行获取。

text 文本

文本(或称之为全文)是普通的、非结构化的文本,例如本段话。默认情况下,文本将被分析为查询词,查询词将被保存在索引中。为能够进行全文搜索,文本字段在索引时将被分析为查询词,查询关键字在搜索时也将被分析为查询词,通过对比查询词是否相同而完成全文搜索。

type 类型

一种类型类似于关系型数据库中的一张表。每种类型都有若干字段,可以用于指定给该类型文档。映射定义了该文档中的每个字段如何进行分析。

参考

Elasticsearch Guide

Elasticsearch Glossary of terms

全文搜索之 Elasticsearch的更多相关文章

  1. Elasticsearch全文搜索——adout

    现在尝试下稍微高级点儿的全文搜索——一项传统数据库确实很难搞定的任务. 搜索下所有喜欢攀岩(rock climbing)的雇员: curl -XGET 'localhost:9200/megacorp ...

  2. 在 Laravel 项目中使用 Elasticsearch 做引擎,scout 全文搜索(小白出品, 绝对白话)

    项目中需要搜索, 所以从零开始学习大家都在用的搜索神器 elasiticsearch. 刚开始 google 的时候, 搜到好多经验贴和视频(中文的, 英文的), 但是由于是第一次接触, 一点概念都没 ...

  3. 使用ElasticSearch服务从MySQL同步数据实现搜索即时提示与全文搜索功能

    最近用了几天时间为公司项目集成了全文搜索引擎,项目初步目标是用于搜索框的即时提示.数据需要从MySQL中同步过来,因为数据不小,因此需要考虑初次同步后进行持续的增量同步.这里用到的开源服务就是Elas ...

  4. ASP.NET Web API + Elasticsearch 6.x 快速做个全文搜索

    最近想做个全文搜索,设想用 ASP.NET Web API + Elasticsearch 6.x 来实现. 网上搜了下 Elasticsearch 的资料,大部分是讲 linux 平台下如何用 ja ...

  5. ElasticSearch 2 (14) - 深入搜索系列之全文搜索

    ElasticSearch 2 (14) - 深入搜索系列之全文搜索 摘要 在看过结构化搜索之后,我们看看怎样在全文字段中查找相关度最高的文档. 全文搜索两个最重要的方面是: 相关(relevance ...

  6. 可以执行全文搜索的原因 Elasticsearch full-text search Kibana RESTful API with JSON over HTTP elasticsearch_action es 模糊查询

    https://www.elastic.co/guide/en/elasticsearch/guide/current/getting-started.html Elasticsearch is a ...

  7. Elasticsearch 全文搜索

    1,匹配查询(match) match查询主要的应用场景是进行全文搜索: // 1,初始化数据 DELETE /my_index PUT /my_index { "settings&quot ...

  8. Elasticsearch系列---深入全文搜索

    概要 本篇介绍怎样在全文字段中搜索到最相关的文档,包含手动控制搜索的精准度,搜索条件权重控制. 手动控制搜索的精准度 搜索的两个重要维度:相关性(Relevance)和分析(Analysis). 相关 ...

  9. Elasticsearch构建全文搜索系统

    目录 前言 一.安装 1.安装elasticsearch 2.启动集群cluster 3.安装管理界面elasticsearch-head 4.安装分词插件elasticsearch-analysis ...

随机推荐

  1. 当前Windows群集心跳阀值设置

    一.内容描述: WINDOWS群集之间通过心跳检测(HeartBeat)各个节点是否正常在线,微软称此检测为lookalive,检测通过UDP数据包中封装的RPC信息进行传送.默认情况下为每秒检测一次 ...

  2. 会务准备期间材料准备工作具体实施总结 ----(vim技巧应用, python信息提取与整合, microsoft word格式调整批量化)

    会务准备期间材料准备工作具体实施总结(vim, python, microsoft word) span.kw { color: #007020; font-weight: bold; } code ...

  3. PYTHON 深拷贝,浅拷贝

    声明:本篇笔记,模仿与其它博客中的内容 浅拷贝 浅拷贝,在内存中只额外创建第一层数据 import copy n1 = {"k1": "wu", "k ...

  4. C# 类动态添加属性、方法

    问题: 需要动态为WPF中的DataGrid添加列,并动态绑定相应数据.(此处仅实现动态属性的添加和使用,关于动态方法的添加和使用详见推荐阅读) 实现关键点: 目标类继承DynamicObject,添 ...

  5. c++ map 的基本操作

    Map是c++的一个标准容器,她提供了很好一对一的关系,在一些程序中建立一个map可以起到事半功倍的效果,总结了一些map基本简单实用的操作!1. map最基本的构造函数:   map<stri ...

  6. NSA,放开那头魔兽!

    面对NSA的觊觎,玩<魔兽世界>的男生们现在恐怕要护好自己的菊花了.   据新浪科技报道,亡命天涯的斯诺登还在持续爆料,最近的爆料和游戏有关:   NSA和英国*通信总署(简称“GCHQ ...

  7. PHP学习笔记:利用时间和mt&lowbar;rand函数获取随机名字

    这个知识会在文件上传等场合用到,还没学面向对象,现在用函数形式呈献给各位,代码都做了备注,有不懂得可以在线提问. <?php /** * Created by PhpStorm. * User: ...

  8. &lbrack;poj 3261&rsqb;Milk Patterns

    后缀数组搞一下就可以了喵~ 其实这道题的第一个想法是 SAM ,建完后缀自动机后拓扑排序跑一遍统计下每个子串的出现次数就 O(N) 就妥妥过掉了 后缀树也是 O(N) 的,统计一下每个节点对应的子树中 ...

  9. 利用预渲染加速iOS设备的图像显示

    最近在做一个UITableView的例子,发现滚动时的性能还不错.但来回滚动时,第一次显示的图像不如再次显示的图像流畅,出现前会有稍许的停顿感.于是我猜想显示过的图像肯定是被缓存起来了,查了下文档后发 ...

  10. JavaScript设计模式接口

    JavaScript中实现接口的方法有三种: 第一种,使用注释的方法实现接口 特点:(1)最简单,但是功能最弱(2)利用 interface和 implement"文字"(3)把他 ...