1. 首页
  2. >
  3. 服务器技术
  4. >
  5. AWS

深入研究ElasticSearch

本文将帮助您深入了解ElasticSearch。 我们将审查可满足典型项目至少95%需求的主要功能。 如果您是ElasticSearch的新手,在本文中您将找到几乎所有在使用新数据库之前应提出的问题的答案。

深入研究ElasticSearch

什么是ElasticSearch?

Elasticsearch是一个全文搜索引擎,用于存储无模式的JSON文档。 Elasticsearch是基于Apache Lucene的开源软件,并根据Apache 2.0许可进行分发。 ElasticSearch可以处理任何类型的数据,包括文本,数字,地理空间,结构化和非结构化。

如何部署

您可以通过Elasticsearch Service(在Amazon Web Services(AWS),Google Cloud Platform(GCP)和阿里云上可用)部署Elasticsearch,也可以将其下载并安装在硬件或云中。

该文档包含有关如何手动下载和安装数据库的说明。

另外,您可以轻松地在Docker上安装Elasticsearch:

1.拉取镜像:

docker pull docker.elastic.co/elasticsearch/elasticsearch:7.4.0


在编写本示例时,最新版本为7.4.0。 在官方网站上检查当前版本。

2.以开发模式运行映像:

docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.4.0


请查看官方文档中的更多选项。

Elasticsearch如何工作

Elasticsearch将文档存储在索引中。 对于关系数据库:索引是一个表,文档是该表中的一行。 该索引是无模式的,因此您可以放置具有不同结构的文档,但是有映射和键限制,我们将在以后概述这些限制。

关于ElasticSearch工作原理的几句话:

· 当您插入某些文档时,ElasticSearch将文档字段的值拆分为标记(例如,句子中的每个单词可以是不同的标记),并将这些标记添加到反向索引中。

· 当用户搜索某个短语时,ElasticSearch将该短语拆分为标记,并将这些标记与反向索引匹配。

如果您不知道什么是倒排索引以及它如何工作,您可以在此处阅读有关倒排索引的简要说明,或查看官方文档。

缩放比例

Elasticsearch是分布式软件,这意味着您可以在集群模式下运行Elasticsearch,在该模式下,每个计算节点将托管一个或多个分片,并充当协调器,将操作委派给正确的分片。 Elasticsearch支持两种最受欢迎的扩展方法,例如分区和复制。

分区

ElasticSearch索引将存储在两个或多个分片上。 您索引的数据将存储在集群中的一个分片上。

复写

ElasticSearch具有一个主碎片和至少一个副本碎片。 您索引的数据将写入主分片和副本分片。 副本是主副本的精确副本。 如果包含主分片的节点发生故障,则副本将接管。

深入研究ElasticSearch

指数

索引是无架构存储,但是您也可以为索引设置严格的文档架构。

创建一个新索引

curl -X PUT http://localhost:9200/person


该命令将创建一个名为" person"的新的无模式索引,如果索引已经存在,则将返回错误。

查看索引信息

curl -X GET http://localhost:9200/person


作为响应,您将看到索引的设置,映射和别名。 如果索引不存在,则会显示错误消息。

架构或映射

映射是对如何存储文档及其包含的字段并在索引中建立索引的描述。 在映射中,可以定义例如以下内容:

· 文档的结构(这些字段的字段和数据类型)

· 索引前如何转换值

· 全文搜索使用哪些字段

使用自定义映射创建索引

curl -X PUT http://localhost:9200/person \-H 'Content-Type: application/json' \-d '{ "mappings": { "dynamic": "strict", "properties": { "name": {"type": "text"}, "email": {"type": "text"}, "location": {"type": "geo_shape"}, "extra_data": {"type": "object", "dynamic": true} } }}'


在此示例中,您将使用静态根结构为文档创建映射。 一个字段是一个动态对象,可以包含任意数量的任何字段(键的数量受索引设置的限制)。

查看现有索引的映射

curl -X GET http://localhost:9200/person


API将返回上一个示例中的现有映射。

资料类型

ElasticSearch支持许多不同的数据类型,以对这些类型执行特定的搜索。 让我们列出最常用的类型:

· 核心数据类型:字符串(文本和关键字),数字(整数,浮点数等),日期,布尔值,二进制数等

· 复杂对象,例如object(hashmap(dictionary))和nested(链表(array))

· 特定的数据类型,例如地理形状,IP等。

每种数据类型都有自己的目的地和设置。 因此,请查阅文档以了解有关每种类型的更多信息。

请注意。 有两种字符串数据类型:文本和关键字。 "文本"用于全文搜索(通常在文本中搜索,具有模糊性和其他功能),"关键字"用于聚合,排序和直接匹配(例如编程语言中的运算符" ==")。

将数据插入索引

插入一个文件

curl -X POST http://localhost:9200/person/_doc \-H 'Content-Type: application/json' \-d '{"name": "John", "age": 30}'


如果成功,此请求将返回生成的ID和其他信息。 但是您总是可以自己指定id:

curl -X POST http://localhost:9200/person/_doc/id-1 \-H 'Content-Type: application/json' \-d '{"name": "Katrin", "age": 25}'


批量插入一个索引

curl -X POST http://localhost:9200/person/_doc/_bulk \-H 'Content-Type: application/json' \-d '{ "index":{} } { "name":"Alex","age":25 } { "index":{} } { "key1":"Amely","age":27 } '


注意:批量添加应以换行符结束。

批量插入不同的索引

curl -X POST http://localhost:9200/_bulk \-H 'Content-Type: application/json' \-d '{ "index":{"_index": "person"} }{ "name":"Jack","age": 34 }{ "index":{"_index": "person"} }{ "name":"Oscar","age":22 }{ "index":{"_index": "person"} }{ "name":"John","age":27 }'


文件类型

在插入URI中,您可以看到" / _doc /"部分。 这是文档的类型,但这是自ElasticSearch版本6起不推荐使用的东西。

更新文件

curl -X POST http://localhost:9200/person/_update/id-1 \-H 'Content-Type: application/json' \-d '{"age": 24}'


这是在一个文档中更新一个字段的简单示例。 Elasticsearch支持针对复杂案例的更复杂查询,因此,请查阅文档以了解更多信息。

深入研究ElasticSearch

搜索查询

你知道,要搜索。 您可以在那里找到所有支持的查询的列表以及这些查询的描述。 在本文中,我们将回顾最常见的查询,这些查询可以覆盖典型项目中95%的用例。

将所有字段匹配到文本

curl -X GET http://localhost:9200/person/_search?q=john


该查询将在任何字段中查找令牌。

全部匹配

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "query": {"match_all": {}}}'


只需返回按ID排序的所有文档即可。

匹配一个

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "query": { "match": { "name": "John Snow" } }}'


"匹配"正在特定字段中寻找特定令牌。 在此示例中,我编写了两个标记,这意味着我们要查找在"名称"字段中包含标记" John",标记" Snow"或这两个标记的文档。 本示例仅适用于一个字段,要按多个字段进行搜索,则需要另一个查询。

匹配词组

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "query": { "match_phrase": { "name": "John Snow" } }}'


此示例与上一个示例之间的区别在于,该示例将在字段中查找完整的短语(在本示例中,将是两个标记" john"和" snow",它们是一个接一个的),并且仅在以下情况下返回结果: 将找到此短语。

如果将两个或多个令牌发送到简单的"匹配",即使仅找到一个令牌,您也将收到结果,但是在" match_phrase"的情况下,您将不会收到结果。

多场比赛

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "query": { "multi_match": { "query": "John", "fields": ["name", "age"], "fuzzines": 3, } }}'


在这种情况下,我们正在所有指定字段中寻找令牌。 多匹配查询支持参数"模糊性",该参数允许使用令牌中的错别字进行搜索。 在这里阅读更多。

术语

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "query": { "term": { "name": { "value": "John" } } }}'


返回在字段中包含确切值的文档。 这意味着,文档中的"名称"字段应完全为"约翰"才能返回此文档。

模糊

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "query": { "fuzzy": { "name": { "value": "Jahn" } } }}'


返回包含与搜索值相似的文档。 这意味着,可搜索值可以有一个错字,如示例中所示。

查看来自搜索查询的典型响应

如果您懒于复制粘贴查询,则可以在此处查看典型响应的正文:

深入研究ElasticSearch

Body of the typical response from ElasticSearch


在响应中,您收到一个对象,该字段是"命中"字段,由内部键"命中"中的所有匹配文档组成,在此键下,您还可以找到"总计"和"最大得分",其中包含有关总计的信息 返回的文档中匹配记录的数量和最高分。 每个文档记录都包含带有文档数据的" _source"以及系统字段,例如索引,类型,ID和评分。

结果排名

计分结果

文档的评分是根据来自指定查询的字段匹配以及您应用于搜索的任何其他配置确定的。 在该文章中,您可以找到有关ElasticSearch评分工作原理的良好描述。 另外,ElasticSearch允许您指定自定义排名功能。 在这里阅读更多。

提高分数

如果您搜索多个字段,并且认为某些字段比其他字段更重要,则可以提高更重要字段的得分。

提高分数意味着,如果某些字段给您分数3,并且您将该字段设置为x2的提升,那么此字段将得出总分数6(3 * 2)。

您可以直接在查询中设置提升。 例如,对于multi_match搜索,要将boost x2设置为字段" key1",将x5设置为字段" key2",则应使用以下格式指定字段:

"fields": ["name^2", "age^5"]


对于其他查询,您可以在搜索查询对象中添加关键字" boost"。 例如:

"fuzzy": {"name": {"value": "John", "boost": 2}}


按某个字段对结果排序

当然,您可以按任何字段而不是分数对结果进行排序。 看下面的例子:

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "sort": [ {"age": {"order": "asc"}}, {"name": {"order": "desc"}}, ], "query": {"match_all": {}}}'


在按字段排序的情况下,所有结果的得分均为零。

AND-OR-NOT或布尔查询

很多情况下,一个条件不足以获取相关结果。 因此,我们需要一些功能来汇总一个查询下的不同条件,进行合取与析取或排除某些结果。 就ElasticSearch而言,这类查询称为布尔查询:

必须(与)

"必须"的工作方式类似于AND。 这意味着运算符中的每个查询都必须出现在文档中。

过滤器(AND不会影响得分)

"过滤器"的工作方式类似于"必须",但不会增加结果的分数。

应该(或)

像OR一样工作。 如果在"应该"下有两个条件,我们将收到所有具有第一个或第二个条件的文件。 此字段会影响评分,这意味着与所有条件匹配的文档比仅与一个条件匹配的文档得分更高。

不得(不)

像NOT一样工作。 符合条件" must_not"下的文档不必出现在结果中。

深入研究ElasticSearch

限制和偏移

在现实世界中,我们经常需要一些限制和补偿来存储结果。 例如,要跳过前5个文档以显示下10个文档,您需要以下查询:

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "from" : 5, "size" : 10, "query": { "match_all": {} }}'


分析仪

在将文档插入索引之前,ElasticSearch会运行分析以准备数据。 分析是将文本转换为令牌的过程,令牌将添加到反向索引中以进行搜索。 分析可以由内置或自定义的分析器执行。 默认情况下,ElasticSearch为每个索引设置标准分析器。 您可以使用分析器将表情符号替换为文本,删除特殊字符,删除停用词等。

集合体

ElasticSearch支持许多聚合框架,可帮助您基于搜索查询聚合数据。 聚集可用于在索引上建立分析信息,或返回唯一值,或检查某个字段中的最小/平均/最大值,或用于其他内容。 查看文档以查看所有Elasticsearch的内置聚合。 可以将多种汇总组合成一个查询。 让我们概述一下构建聚合查询的难易程度:

curl -X GET http://localhost:9200/person/_search \-H 'Content-Type: application/json' \-d '{ "aggs" : { "avg_age_key" : { "avg" : { "field" : "age" } }, "max_age_key" : { "max" : { "field" : "age" } }, "min_age_key" : { "min" : { "field" : "age" } }, "uniq_age_key" : { "terms" : { "field" : "age" } } }}'


在此示例中,我将4个聚合命令放入一个查询中。 您可以很容易地理解这些聚合的每个功能。 在响应中,您可以在响应对象底部的键"聚合"下找到聚合结果。

MapReduce

聚合使您可以对索引进行良好的分析。 但是,如果您需要对驻留在大型Elasticsearch集群上的大量数据进行复杂的分析,换句话说,您拥有大数据,Elasticsearch将为您提供机会在索引上运行MapReduce作业。 查看官方文档以了解更多信息。

事物次数

ElasticSearch不支持事物。

摘要

列出的所有优点和功能都允许在许多不同情况下使用Elasticsearch:

· 申请和网站搜索

· 企业搜寻

· 记录和日志分析

· 监控许多指标

· 地理空间数据分析和可视化

· 安全或业务分析

并且有很多基于ElasticSearch的即用型产品(例如Kibana,Elastic Stack等)使您可以花费更少的钱和更少的时间来开发解决方案。

(本文翻译自Ihor Kopanev的文章《Dive into ElasticSearch》,参考:https://towardsdatascience.com/dive-into-elasticsearch-fbf848e8cf08)