微微陌上矣 - ElasticSearch
type: channel
link: http://www.cynthia99.link/index.php/tag/ElasticSearch
items: ElasticSearch -数据聚合
items: ElasticSearch -DSL语法
items: ElasticSearch 索引库操作

ElasticSearch -数据聚合
type: item
date: 2022-04-05T22:13:00+08:00
description: 分布式搜索引擎 -数据聚合 详细项目可见：ElasticSearch-search 学习目标 1.数据聚合 聚合（aggregations）可以让我们极其方便的实现对数据的统计、分析、运算。例如： 什么品牌的手机最受欢迎？ 这些手机的平均价格、最高价格、最低价格？ 这些手机每月的销售情况如何？ 实现这些统计功能的比数据库的sql要方便的多，而且查询速度非常快，可以实现近实时搜索效果。 1.1.聚合的种类 聚合常见的有三类： 桶（Bucket）聚合：用来对文档做分组 TermAggregation：按照文档字段值分组，例如按照品牌值分组、按照国家分组 Date Histogram：按照日期阶梯分组，例如一周为一组，或者一月为一组 度量（Metric）聚合：用以计算一些值，比如：最大值、最小值、平均值等 Avg：求平均值 Max：求最大值 Min：求最小值 Stats：同时求max、min、avg、sum等 管道（pipeline）聚合：其它聚合的结果为基础做聚合 注意：参加聚合的字段必须是keyword、日期、数值、布尔类型 1.2.DSL实现聚合 现在，我们要统计所有数据中的酒店品牌有几种，其实就是按照品牌对数据分组。此时可以根据酒店品牌的名称做聚合，也就是Bucket聚合。 1.2.1.Bucket聚合语法 语法如下： GET /hotel/_search { "size": 0, // 设置size为0，结果中不包含文档，只包含聚合结果 "aggs": { // 定义聚合 "brandAgg": { //给聚合起个名字 "terms": { // 聚合的类型，按照品牌值聚合，所以选择term "field": "brand", // 参与聚合的字段 "size": 20 // 希望获取的聚合结果数量 } } } } 结果如图： 1.2.2.聚合结果排序 默认情况下，Bucket聚合会统计Bucket内的文档数量，记为_count，并且按照_count降序排序。 我们可以指定order属性，自定义聚合的排序方式： GET /hotel/_search { "size": 0, "aggs": { "brandAgg": { "terms": { "field": "brand", "order": { "_count": "asc" // 按照_count升序排列 }, "size": 20 } } } } 1.2.3.限定聚合范围 默认情况下，Bucket聚合是对索引库的所有文档做聚合，但真实场景下，用户会输入搜索条件，因此聚合必须是对搜索结果聚合。那么聚合必须添加限定条件。 我们可以限定要聚合的文档范围，只要添加query条件即可： GET /hotel/_search { "query": { "range": { "price": { "lte": 200 // 只对200元以下的文档聚合 } } }, "size": 0, "aggs": { "brandAgg": { "terms": { "field": "brand", "size": 20 } } } } 这次，聚合得到的品牌明显变少了： 1.2.4.Metric聚合语法 上节课，我们对酒店按照品牌分组，形成了一个个桶。现在我们需要对桶内的酒店做运算，获取每个品牌的用户评分的min、max、avg等值。 这就要用到Metric聚合了，例如stat聚合：就可以获取min、max、avg等结果。 语法如下： GET /hotel/_search { "size": 0, "aggs": { "brandAgg": { "terms": { "field": "brand", "size": 20 }, "aggs": { // 是brands聚合的子聚合，也就是分组后对每组分别计算 "score_stats": { // 聚合名称 "stats": { // 聚合类型，这里stats可以计算min、max、avg等 "field": "score" // 聚合字段，这里是score } } } } } } 这次的score_stats聚合是在brandAgg的聚合内部嵌套的子聚合。因为我们需要在每个桶分别计算。 另外，我们还可以给聚合结果做个排序，例如按照每个桶的酒店平均分做排序： 1.2.5.小结 aggs代表聚合，与query同级，此时query的作用是？ 限定聚合的的文档范围 聚合必须的三要素： 聚合名称 聚合类型 聚合字段 聚合可配置属性有： size：指定聚合结果数量 order：指定聚合结果排序方式 field：指定聚合字段 1.3.RestAPI实现聚合 1.3.1.API语法 聚合条件与query条件同级别，因此需要使用request.sour…

ElasticSearch -DSL语法
type: item
date: 2022-04-05T21:58:00+08:00
description: 分布式搜索引擎 ElasticSearch 在昨天的学习中，我们已经导入了大量数据到elasticsearch中，实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以今天，我们研究下elasticsearch的数据搜索功能。我们会分别使用DSL和RestClient实现搜索。 学习目标 1.DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL（Domain Specific Language）来定义查询。常见的查询类型包括： 查询所有：查询出所有数据，一般测试用。例如：match_all 全文检索（full text）查询：利用分词器对用户输入内容分词，然后去倒排索引库中匹配。例如： match_query multi_match_query 精确查询：根据精确词条值查找数据，一般是查找keyword、数值、日期、boolean等类型字段。例如： ids range term 地理（geo）查询：根据经纬度查询。例如： geo_distance geo_bounding_box 复合（compound）查询：复合查询可以将上述各种查询条件组合起来，合并查询条件。例如： bool function_score 查询的语法基本一致： GET /indexName/_search { "query": { "查询类型": { "查询条件": "条件值" } } } 我们以查询所有为例，其中： 查询类型为match_all 没有查询条件 // 查询所有 GET /indexName/_search { "query": { "match_all": { } } } 其它查询无非就是查询类型、查询条件的变化。 1.2.全文检索查询 1.2.1.使用场景 全文检索查询的基本流程如下： 对用户搜索的内容做分词，得到词条 根据词条去倒排索引库中匹配，得到文档id 根据文档id找到文档，返回给用户 比较常用的场景包括： 商城的输入框搜索 百度输入框搜索 例如京东： 因为是拿着词条去匹配，因此参与搜索的字段也必须是可分词的text类型的字段。 1.2.2.基本语法 常见的全文检索查询包括： match查询：单字段查询 multi_match查询：多字段查询，任意一个字段符合条件就算符合查询条件 match查询语法如下： GET /indexName/_search { "query": { "match": { "FIELD": "TEXT" } } } mulit_match语法如下： GET /indexName/_search { "query": { "multi_match": { "query": "TEXT", "fields": ["FIELD1", " FIELD12"] } } } 1.2.3.示例 match查询示例： multi_match查询示例： 可以看到，两种查询结果是一样的，为什么？ 因为我们将brand、name、business值都利用copy_to复制到了all字段中。因此你根据三个字段搜索，和根据all字段搜索效果当然一样了。 但是，搜索字段越多，对查询性能影响越大，因此建议采用copy_to，然后单字段查询的方式。 1.2.4.总结 match和multi_match的区别是什么？ match：根据一个字段查询 multi_match：根据多个字段查询，参与查询字段越多，查询性能越差 1.3.精准查询 精确查询一般是查找keyword、数值、日期、boolean等类型字段。所以不会对搜索条件分词。常见的有： term：根据词条精确值查询 range：根据值的范围查询 1.3.1.term查询 因为精确查询的字段搜是不分词的字段，因此查询的条件也必须是不分词的词条。查询时，用户输入的内容跟自动值完全匹配时才认为符合条件。如果用户输入的内容过多，反而搜索不到数据。 语法说明： // term查询 GET /indexName/_search { "query": { "term": { "FIELD": { "value": "VALUE" } } } } 示例： 当我搜索的是精确词条时，能正确查询出结果： 但是，当我搜索的内容不是词条，而是多个词语形成的短语时，反而搜索不到： 1.3.2.range查询 范围查询，一般应用在对数值类型做范围过滤的时候。比如做价格范围过滤。 基本语法： // range查询 GET /indexName/_search { "query": { "range": { "FIELD": { "gte": 10…

ElasticSearch 索引库操作
type: item
date: 2022-04-04T22:45:00+08:00
description: 分布式搜索引擎 -- ElasticSearch基础 学习目标 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎，具备非常多强大功能，可以帮助我们从海量数据中快速找到需要的内容 例如： 在GitHub搜索代码 1.1.2.ELK技术栈 elasticsearch结合kibana、Logstash、Beats，也就是elastic stack（ELK）。被广泛应用在日志数据分析、实时监控等领域： 而elasticsearch是elastic stack的核心，负责存储、搜索、分析数据。 1.1.3.为什么不是其他搜索技术？ 目前比较知名的搜索引擎技术排名： 虽然在早期，Apache Solr是最主要的搜索引擎技术，但随着发展elasticsearch已经渐渐超越了Solr，独占鳌头： 1.1.5.总结 什么是elasticsearch？ 一个开源的分布式搜索引擎，可以用来实现搜索、日志统计、分析、系统监控等功能 什么是elastic stack（ELK）？ 是以elasticsearch为核心的技术栈，包括beats、Logstash、kibana、elasticsearch 什么是Lucene？ 是Apache的开源搜索引擎类库，提供了搜索引擎的核心API 1.2.倒排索引 倒排索引的概念是基于MySQL这样的正向索引而言的。 1.2.1.正向索引 那么什么是正向索引呢？例如给下表（tb_goods）中的id创建索引： 如果是根据id查询，那么直接走索引，查询速度非常快。 但如果是基于title做模糊查询，只能是逐行扫描数据，流程如下： 1）用户搜索数据，条件是title符合"%手机%" 2）逐行获取数据，比如id为1的数据 3）判断数据中的title是否符合用户搜索条件 4）如果符合则放入结果集，不符合则丢弃。回到步骤1 逐行扫描，也就是全表扫描，随着数据量增加，其查询效率也会越来越低。当数据量达到数百万时，就是一场灾难。 1.2.2.倒排索引 倒排索引中有两个非常重要的概念： 文档（Document）：用来搜索的数据，其中的每一条数据就是一个文档。例如一个网页、一个商品信息 词条（Term）：对文档数据或用户搜索数据，利用某种算法分词，得到的具备含义的词语就是词条。例如：我是中国人，就可以分为：我、是、中国人、中国、国人这样的几个词条 创建倒排索引是对正向索引的一种特殊处理，流程如下： 将每一个文档的数据利用算法分词，得到一个个词条 创建表，每行数据包括词条、词条所在文档id、位置等信息 因为词条唯一性，可以给词条创建索引，例如hash表结构索引 如图： 倒排索引的搜索流程如下（以搜索"华为手机"为例）： 1）用户输入条件"华为手机"进行搜索。 2）对用户输入内容分词，得到词条：华为、手机。 3）拿着词条在倒排索引中查找，可以得到包含词条的文档id：1、2、3。 4）拿着文档id到正向索引中查找具体文档。 如图： 虽然要先查询倒排索引，再查询倒排索引，但是无论是词条、还是文档id都建立了索引，查询速度非常快！无需全表扫描。 1.2.3.正向和倒排 那么为什么一个叫做正向索引，一个叫做倒排索引呢？ 正向索引是最传统的，根据id索引的方式。但根据词条查询时，必须先逐条获取每个文档，然后判断文档中是否包含所需要的词条，是根据文档找词条的过程。 而倒排索引则相反，是先找到用户要搜索的词条，根据词条得到保护词条的文档的id，然后根据id获取文档。是根据词条找文档的过程。 是不是恰好反过来了？ 那么两者方式的优缺点是什么呢？ 正向索引： 优点： 可以给多个字段创建索引 根据索引字段搜索、排序速度非常快 缺点： 根据非索引字段，或者索引字段中的部分词条查找时，只能全表扫描。 倒排索引： 优点： 根据词条搜索、模糊搜索时，速度非常快 缺点： 只能给词条创建索引，而不是字段 无法根据字段做排序 1.3.es的一些概念 elasticsearch中有很多独有的概念，与mysql中略有差别，但也有相似之处。 1.3.1.文档和字段 elasticsearch是面向文档（Document）存储的，可以是数据库中的一条商品数据，一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中： 而Json文档中往往包含很多的字段（Field），类似于数据库中的列。 1.3.2.索引和映射 索引（Index），就是相同类型的文档的集合。 例如： 所有用户文档，就可以组织在一起，称为用户的索引； 所有商品的文档，可以组织在一起，称为商品的索引； 所有订单的文档，可以组织在一起，称为订单的索引； 因此，我们可以把索引当做是数据库中的…