Fivk博客 - elasticsearch
type: channel
link: https://blog.fivk.cn/tag/elasticsearch/
items: 【微服务】elasticsearch分布式搜索引擎（下）
items: 【微服务】elasticsearch分布式搜索引擎（中）

【微服务】elasticsearch分布式搜索引擎（下）
type: item
date: 2023-12-10T16:28:57+08:00
description: 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.source()来指定聚合条件。聚合条件的语法：聚合的结果也与查询结果不同，API也比较特殊。不过同样是JSON逐层解析：1.3.2.业务需求需求：搜索页面的品牌、城市等信息不应该是在页面写死，而是通过聚合索…

【微服务】elasticsearch分布式搜索引擎（中）
type: item
date: 2023-11-14T09:01:00+08:00
description: 0.学习目标在昨天的学习中，我们已经导入了大量数据到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_querymulti_match_query精确查询：根据精确词条值查找数据，一般是查找keyword、数值、日期、boolean等类型字段。例如：idsrangeterm地理（geo）查询：根据经纬度查询。例如：geo_distancegeo_bounding_box复合（compound）查询：复合查询可以将上述各种查询条件组合起来，合并查询条件。例如：boolfunction_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, // 这里的gte代表大于等于，gt则代表大于 "lte": 20 // lte代表小于等于，lt则代表小于 } } } }示例：1.3.3.总结精确查询常见的有哪些？term查…