Elasticsearch基本概念及使用

Elasticsearch 是一个开源的、分布式的全文搜索和分析引擎,基于 Apache Lucene 构建。它提供了快速的搜索能力,支持大规模的数据分析,广泛应用于日志分析、全文搜索、监控系统和商业智能等领域。ES操作指令是基于restAPI构建,也就是说,操作ES需要向其服务端口发送http请求,ES会根据请求类型、uri、请求参数等,决定具体行为。

文章中涉及的指令操作,都会在Kibana提供的devtool中执行,可以查看我的文章Elasticsearch集群及Kibana部署流程,对其进行部署后学习。

1. 存储数据结构

ES通过索引定义存储数据的结构,什么是索引呢?我们可以类型数据库的表,索引和数据库的表极为类似,可以存储一种数据类型的数据。在6版本及之前,索引可以存储多种数据类型的数据,更像是数据库,而7版本及之后,索引只可以存储一种数据结构。

ES通过json类型存储数据,索引本质上就是一种json结构,其中包含了多个属性,其中mapping属性中定义了索引中存储类型的结构,我们称其为映射,映射就可以类比为数据库的表结构,其中定义了索引可以存储那种结构的json,以及作为搜索引擎时,其属性的搜索规则等。

除了映射外,索引中还包含setting属性,其定义了当前索引的一切特性,甚至集群表现,如果当前索引的集群分片数,副本数(ES的集群分片可以针对索引设置,大大提高了优化性能的可操作性)等索引特性。

除此之外,还包括aliaes(索引别名),完整属性如下:

{"settings": {// 索引的基础配置部分"number_of_shards": 1, // 主分片数量,决定索引的水平扩展性"number_of_replicas": 1, // 每个主分片的副本数,提升数据冗余性和查询性能"refresh_interval": "1s", // 刷新间隔时间,默认 1 秒。数据可见性延迟的控制参数"max_result_window": 10000, // 查询分页的最大窗口大小,默认 10000"max_inner_result_window": 100, // 嵌套分页的最大窗口大小,控制内嵌对象的分页深度"max_rescore_window": 10000, // 重新评分窗口的最大值"max_docvalue_fields_search": 100, // 查询中允许的 doc_value 字段数量上限,避免性能问题"max_script_fields": 32, // 查询中允许的脚本字段最大数量"max_ngram_diff": 1, // ngram 分析器的最小和最大长度之差,影响文本分析的粒度"max_shingle_diff": 3, // shingle 分析器的最小和最大长度之差,影响分词的组合方式"analysis": {// 定义分析器、字符过滤器、词汇过滤器等分析组件"analyzer": {"default": {"type": "standard" // 默认使用标准分词器,适合通用文本分词},"custom_analyzer": {"type": "custom","tokenizer": "whitespace", // 自定义分词器,使用空白分词"filter": ["lowercase"] // 词汇过滤器,转换为小写字母}}},"index.lifecycle.name": "my_policy", // 生命周期策略名称,自动管理索引的生命周期"index.lifecycle.rollover_alias": "my_alias", // 用于自动 rollover 的别名,适合日志索引管理"routing_partition_size": 1, // 路由分区大小,影响数据路由的灵活性"codec": "best_compression", // 压缩算法,可选 `best_compression` 提高存储效率"translog.durability": "request", // 事务日志的持久性,`request` 表示每次请求刷盘"priority": 1, // 索引优先级,适用于恢复时控制恢复顺序"queries.cache.enabled": true // 查询缓存开关,提升重复查询性能},"mappings": {// 索引的字段映射配置"dynamic": "strict", // 动态映射设置,`strict` 表示严格模式,禁止未知字段"date_detection": true, // 自动日期检测,启用时会自动识别日期字段"numeric_detection": true, // 自动数值检测,启用时会自动识别整数和浮点数"dynamic_date_formats": ["yyyy-MM-dd"], // 定义动态日期格式,用于日期类型自动识别"properties": {"example_field": {"type": "text",                // 字段的数据类型,如 text、keyword、integer、date 等"analyzer": "standard",         // 指定索引时的分析器"search_analyzer": "whitespace",// 指定搜索时的,与 analyzer 可以不同"boost": 1.0,                   // 相关性评分的权重,值越高权重越大"index": true,                  // 是否对该字段建立索引,默认 true"store": false,                 // 是否将字段单独存储在 _source 外部"doc_values": true,             // 启用或禁用 doc_values,适用于排序、聚合"norms": true,                  // 控制是否启用字段的归一化信息,用于相关性评分"similarity": "BM25",           // 设置相似性算法,默认使用 BM25,可选 classic 等"null_value": "NULL",           // 当字段为空时的默认值"ignore_above": 256,            // 忽略超过指定长度的字符串,适用于 keyword 类型"position_increment_gap": 100,  // 控制数组中元素的短语查询间隔"index_options": "positions",   // 控制索引选项,如 docs, freqs, positions"term_vector": "yes",           // 存储词条向量信息,用于高亮显示等"coerce": true,                 // 强制将非预期类型转换为指定类型,适用于数值类型"copy_to": "another_field",     // 将字段内容复制到另一个字段,用于合并搜索"eager_global_ordinals": false, // 提前加载全局排序,适用于高频使用的 keyword 字段"scaling_factor": 100,          // 用于存储浮点数时将其转换为 long 类型的倍率"format": "yyyy-MM-dd",         // 日期格式,用于 date 类型字段的格式定义"fields": {                     // 定义多字段结构,支持多个索引方式"keyword": {"type": "keyword","ignore_above": 256}},"enabled": true,                // 是否启用该字段,适用于 object 类型字段"dynamic": "strict",            // 控制动态映射,strict 表示未知字段会报错"time_series_dimension": true,  // 是否将字段设为时间序列维度,适用于时序数据"meta": {                       // 字段的元数据,用于附加描述信息"description": "Example field for documentation purposes."},"split_queries_on_whitespace": false // 用于 text 类型,控制查询是否按空格分词}}"enabled": true // 启用或禁用整个索引映射,`false` 会忽略整个映射},"aliases": {// 索引的别名部分"my_alias": {}, // 简单别名,直接指向索引"filtered_alias": {// 带筛选条件的别名,适用于部分查询场景"filter": {"term": { "active": true } // 仅匹配 active 为 true 的文档},"routing": "1" // 路由设置,控制查询或写入操作的路由方式}}
}

这就是一个非常完整的一个索引,当然其中绝大部份属性,我们都使用不到。

数据类型

Elasticsearch(ES)支持多种数据类型,但部分数据类型同常见语言中的不一致。以下是 ES 中常用的数据类型及其详细说明(不建议记住,大部分用不上):

1. 核心基础类型
  • text:适用于全文搜索的文本数据类型。通常用于长文本字段,如产品描述、文章内容等。text 类型字段会进行分词和倒排索引,支持全文搜索。
  • keyword:适用于精确匹配的文本数据。keyword 类型字段不分词,用于存储不需要分析的字符串,如用户名、标签等。适合排序、聚合和过滤。
  • integer:32 位整数类型,用于存储整型数据。适用于数值范围在 ±2,147,483,647 的数据。
  • long:64 位整数类型,用于存储更大范围的整型数据,数值范围在 ±9,223,372,036,854,775,807。
  • float:32 位浮点数类型,适合存储带有小数的数值,精度较低。
  • double:64 位浮点数类型,精度更高,适合存储高精度的数值数据。
  • boolean:布尔类型,用于存储 truefalse 值。
  • date:用于存储日期数据,可以支持多种日期格式(如 yyyy-MM-dd),也可以存储时间戳(毫秒或秒)。支持日期范围查询。
  • binary:用于存储二进制数据(Base64 编码格式)。通常用于存储图片、文件等非结构化数据,不支持搜索。
2. 复合类型
  • object:用于存储 JSON 对象。object 类型字段可以包含子字段,适合嵌套数据结构。注意:object 类型的子字段会被展开并作为顶级字段索引。
  • nested:嵌套对象类型,用于存储数组中的 JSON 对象。与 object 不同,nested 类型会为数组中的每个对象单独创建一个索引,支持更复杂的嵌套查询。
3. 专用类型
  • geo_point:用于存储地理坐标点(经纬度),支持地理位置的距离计算和位置范围查询。常用于地理位置检索。
  • geo_shape:用于存储复杂的地理形状,如多边形、线条等。适合更高级的地理空间计算,比如区域包含、相交等查询。
  • ip:用于存储 IP 地址(IPv4 和 IPv6),支持范围查询和 IP 地址过滤。
  • range:用于存储一个范围,支持以下几种范围类型:
    • integer_range:整型范围。
    • float_range:浮点数范围。
    • long_range:长整型范围。
    • double_range:双精度浮点数范围。
    • date_range:日期范围,适合时间段查询。
4. 专门的数据类型(Elasticsearch 7.10 引入)
  • alias:字段别名,指向索引中现有字段的引用。用于访问实际字段的数据或改变字段名称,而不需要复制字段内容。
  • dense_vectorsparse_vector:用于存储向量数据,通常用于机器学习和相似性计算。
  • rank_featurerank_features:用于存储特征值,用于机器学习模型的排序字段。

操作指令

对于索引结构中的属性进行操作或执行ES提供的一些指令时,通常需要在前面加一个 _ ,而我们自己定义的属性则不需要

1.添加索引

我们可以通过发送get请求的方式添加索引,具体如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 查询索引

查询索引需要通过get请求加索引名称,具体如下:

在这里插入图片描述

3. 查询全部索引

通过get请求加_cat/indices?v的uri的形式,查询全部索引,具体如下

_cat不仅仅是查询所有索引的作用,他的主要作用是查询当前ES集群的元数据信息。

在这里插入图片描述

其中可以看到我们刚刚创建的索引

4. 查询当前索引是否存在

我们可以通过Head请求查询索引是否存在,具体如下

在这里插入图片描述

5. 修改索引属性(mapping,setting,alias)

在上文我们已经说过,当修改索引属性时,需要在属性前加上一个 _ ,所以我们可以通过put请求,加上/索引名/_索引属性的形式,进行修改,具体如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注:这种修改操作,对于原来没有的属性会进行新增,而对于已经有的属性则会修改,不过索引中并非所有属性都能够修改,如果修改不能修改的属性则会报错

6. 删除索引

通过delete请求,可以删除索引,具体如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7. 索引批处理

我们还可以通过_mget和_bulk对索引进行批处理,实例如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图中docs是一个数组可以传入多个条件,并且以其他任何属性为条件

_mget用于批量查询,而剩下的增删改则是全权有bulk负责
在这里插入图片描述

除了删除外,其他的都是第一行是操作及搜索条件,第二行是新数据。

index和create都是插入数据,不同的是index对于已经存在的数据会进行覆盖,而create会报错。

2. 文档

索引中的属性定义了存储数据的结构,及索引的特性,而真实的数据则存储在索引所对应的文档中,一次文档查询的结果如下:

{"took": 5, // 查询耗时,单位为毫秒,表示从发送请求到获得结果的时间"timed_out": false, // 是否超时,false 表示查询在规定时间内完成"_shards": { // 与查询相关的分片统计信息"total": 5, // 查询涉及的分片总数"successful": 5, // 成功响应的分片数量"skipped": 0, // 被跳过的分片数量(例如,索引为空时的分片可能被跳过)"failed": 0 // 查询失败的分片数量},"hits": { // 匹配的文档集合"total": { // 匹配的文档总数"value": 2, // 查询条件下的匹配文档数量"relation": "eq" // 匹配总数的关系。eq 表示精确数量,gte 表示大于或等于该数量},"max_score": 1.0, // 最高相关性得分,表示匹配度最高的文档的得分"hits": [ // 匹配的文档数组,每个元素代表一个文档的完整信息{"_index": "my_index", // 文档所属的索引名称"_type": "_doc", // 文档的类型(7.x 版本后仅为 _doc)"_id": "1", // 文档的唯一标识符,等同于数据库中的主键"_score": 1.0, // 文档的相关性得分,表示文档与查询的匹配程度"_source": { // 文档的实际内容"name": "Alice", // 文档中的字段"age": 30, // 文档中的字段}},{"_index": "my_index","_type": "_doc","_id": "2","_score": 1.0,"_source": {"name": "Bob","age": 25,"email": "bob@example.com","status": "inactive"}}]}
}

其中hits.hits数组为查询结果列表,而列表中的每个元素的_source属性则是具体数据。

具体操作

我们再次创建一个索引,用于定义数据结构,然后在执行文档相关操作,创建指令如下:

PUT test_index
{"mappings": {"properties": {"name": {"type": "text"},"age": {"type": "integer"}}}
}
1. 新增数据

通过post或put请求,以及/索引名/_doc的uri/id(id也可以不写,由ES自动生成),可以完成新增一条数据,具体如下:

在这里插入图片描述

2. 查询数据

通过get请求,以及_search,搜索全部数据(search可以分词搜索,下面说)

在这里插入图片描述

也可以通过_doc根据id查找

在这里插入图片描述

3. 更改数据

通过_update,可以将指定字段更改(没有指定的不会改变)

在这里插入图片描述

4. 删除数据

通过delete请求可以删除数据

在这里插入图片描述

3. ES的搜索功能

ES中并非所有类型都支持搜索功能,并且支持搜索功能的类型,而可以进行搜索的类型有可以细分为精确搜索(只支持精确搜索),分词搜索和范围搜索

精确搜索
  • keyword:用于精确匹配的字符串搜索,支持过滤、排序和聚合,但不分词。

  • boolean:可以用于布尔值的精确匹配查询。

分词搜索
  • text:用于全文搜索,支持分词、相关性评分、模糊搜索等。
范围搜索
  • date:支持日期范围查询,可以用于过滤、排序、聚合。

  • ip:可以用于 IP 地址的精确匹配和范围查询(支持 IPv4 和 IPv6)。

  • geo_point:用于地理坐标点查询,支持地理距离计算和区域范围查询。

  • range(包括 integer_rangefloat_rangelong_rangedouble_rangedate_range):可以用于范围查询和范围过滤。

剩余的二进制数据**binary,以及object(非嵌套对象)和nested**:支持复杂的嵌套对象都不支持搜索(对象字段支持搜索)。

具体操作

为了方便操作,我们执行以下指令创建一个索引,并插入数据:

#创建索引
PUT /test_search_index
{"mappings": {"properties": {"title": {"type": "text"},"tags": {"type": "keyword"},"publish_date": {"type": "date","format": "yyyy-MM-dd"},"author": {"type": "keyword"},"views": {"type": "integer"},"price": {"type": "float"},"active": {"type": "boolean"},"ip_address": {"type": "ip"},"location": {"type": "geo_point"}}}
}
#一次性插入多条数据
POST /test_search_index/_bulk
{ "index": { "_id": 1 }}
{ "title": "Elasticsearch Guide", "tags": ["search", "guide"], "publish_date": "2023-01-01", "author": "Alice", "views": 100, "price": 9.99, "active": true, "ip_address": "192.168.1.1", "location": "40.730610,-73.935242" }
{ "index": { "_id": 2 }}
{ "title": "Advanced Search", "tags": ["elasticsearch", "search"], "publish_date": "2023-02-01", "author": "Bob", "views": 200, "price": 15.50, "active": false, "ip_address": "192.168.1.2", "location": "34.052235,-118.243683" }
{ "index": { "_id": 3 }}
{ "title": "Elasticsearch and Python", "tags": ["python", "elasticsearch"], "publish_date": "2023-03-15", "author": "Carol", "views": 150, "price": 20.00, "active": true, "ip_address": "192.168.1.3", "location": "51.507351,-0.127758" }
{ "index": { "_id": 4 }}
{ "title": "Text Analysis with Elasticsearch", "tags": ["analysis", "text"], "publish_date": "2023-04-20", "author": "Dave", "views": 300, "price": 25.99, "active": true, "ip_address": "192.168.1.4", "location": "35.689487,139.691711" }
{ "index": { "_id": 5 }}
{ "title": "Geo Search", "tags": ["geo", "search"], "publish_date": "2023-05-10", "author": "Eve", "views": 250, "price": 30.00, "active": false, "ip_address": "192.168.1.5", "location": "48.856613,2.352222" }
{ "index": { "_id": 6 }}
{ "title": "Keyword Search", "tags": ["keyword", "exact"], "publish_date": "2023-06-12", "author": "Frank", "views": 120, "price": 8.99, "active": true, "ip_address": "192.168.1.6", "location": "55.755825,37.617298" }
{ "index": { "_id": 7 }}
{ "title": "Boolean Queries", "tags": ["boolean", "queries"], "publish_date": "2023-07-15", "author": "Grace", "views": 80, "price": 12.49, "active": false, "ip_address": "192.168.1.7", "location": "39.904202,116.407394" }
{ "index": { "_id": 8 }}
{ "title": "Range Queries", "tags": ["range", "queries"], "publish_date": "2023-08-20", "author": "Hank", "views": 180, "price": 17.75, "active": true, "ip_address": "192.168.1.8", "location": "37.774929,-122.419418" }
{ "index": { "_id": 9 }}
{ "title": "Sorting Results", "tags": ["sorting", "results"], "publish_date": "2023-09-25", "author": "Ivy", "views": 220, "price": 22.00, "active": true, "ip_address": "192.168.1.9", "location": "40.712776,-74.005974" }
{ "index": { "_id": 10 }}
{ "title": "Faceted Search", "tags": ["facets", "search"], "publish_date": "2023-10-30", "author": "Jack", "views": 90, "price": 19.95, "active": false, "ip_address": "192.168.1.10", "location": "41.878113,-87.629799" }
1. 精确搜索

在这里插入图片描述

除了必须精确查找的类型外,很多范围查找的也可以使用精确查找,在图中我们也可以发现一个问题,就是tags属性不是数组吗?不过ES可并没有提供一个数组类型啊!

实际上这个数组字段的类型就是keyword,ES中的数组元素必须为同一个类型,也就是是其索引中设置的类型。

搜索中我们使用了query.term来进行搜索,除此之外还有一个query.match搜索的,是用来做分词搜索的,区别在于query.match在查询是会讲查询语句进行分词处理,而query.term则不会。

2. 范围搜索

在这里插入图片描述

3. 分词查询

text是唯一支持分词查询的类型,我们可以在创建改字段时通过改变analyzer属性,选择分析器(默认是standard),然后存入的文本就会根据分词的规则对文本进行分词,生成倒排索引,那么什么是倒排索引呢?假设我门存入一段文字,我爱你中国,那么这段文字可能会被分词为我、爱、你、中国、我爱你,这些词,这这些词又会作为索引指向文本,当我们搜索我爱你时,就会找到这个索引,并返回对应文本,这就是倒排索引。

我们可以通过可以如下请求,对title字段进行搜索,为了方便展示,我们用source属性进行限制,只让他展示title:

在这里插入图片描述

通过图中结果我们可以推测我们的文本被分词为Elasticsearch和guide两个词,然后去ES中搜索倒排索引,并根据结果进行评分(也就是结果的_score属性),评分越高,结果越靠前,最终结果如图所示。

过滤器

过滤器本质是是和query相同的属性,作用和语法都相同,不同的是,filter不会对结果进行评分排序,并且会对结果进行缓存。也就是说filter的查询性能比query更好,这里就不举例了,和query语法一样。

组合查询

组合查询通过如下语法实现:

GET /my_index/_search
{"query": {"bool": {"must": [{ "term": { "status": "active" }},               // 必须为 active{ "range": { "age": { "gte": 25, "lte": 40 }}}   // 年龄在 2540 之间],"should": [{ "match": { "description": "Elasticsearch" }}   // 描述包含 Elasticsearch],"must_not": [{ "match": { "description": "beginner" }}        // 描述不包含 beginner],"minimum_should_match": 2}}
}

其中bool代表了组合查询,而其中must中的查询条件必须全部满足,而should中包含的条件只需要满足一个即可,must_not则是必须不满足,而minimum_should_match表示的是当前组合查询中的should语句知道满足多少条时才返回true,也就是不再只是满足一条就返回true了。

must得到的结果仍然要参与评分,我们可以用filter替换must,实现和过滤器一样的效果。

bool本身也可以作为组合查询的条件之一,也就是死后缩bool也可以作为bool的属性。

4. 分析器

Elasticsearch对于text类型的处理依赖于分析器,分析器能够将text类型文本,按照既定的规则处理为可以搜索的一个个倒排索引。分析器的整个执行过程分为三个阶段,分别是分词前对于字符串的处理,分词,以及分词后对于每个索引的处理,对应的也是分析器的三个部分,分别是字符过滤器,分词器,分词过滤器(或者词条,或者令牌,叫法很多)。

ES中默认了内置了很多的分析器,内容如下:

  • 标准分析器(standard):按语言规则进行分词,将所有词条转为小写,适合一般文本处理。
  • 简单分析器(simple):按非字母字符分词,将词条转换为小写,适合不包含复杂字符的简单文本。
  • 空格分析器(whitespace):按空格分词,不做大小写转换,适合对空格分隔的内容进行简单处理。
  • 停止词分析器(stop):类似标准分析器,分词后去除停用词(如 “and”、“the” 等),适合英文内容的分词处理。
  • 关键词分析器(keyword):将整个文本视为一个词条,不进行分词,适合精确匹配(如邮箱地址或用户ID)。
  • 语言分析器(language,如 english、french、german):针对特定语言进行分词和处理,去掉停用词并进行词干提取,适用于多语言文本。
  • 模式分析器(pattern):基于正则表达式分词,按自定义分隔模式拆分,适合按特定字符或模式分隔的内容。
  • UAX_URL_Email 分析器(uax_url_email):识别 URL 和电子邮件地址作为单独词条,适用于带 URL 或电子邮件的内容。
  • 自定义分析器(custom):用户自定义的分词方式,灵活组合字符过滤、分词和过滤规则,用于满足特殊的文本处理需求。

这些内置的分析器,都是可以直接配置给text类型属性使用的。

4.1 字符过滤器

字符过滤器用于在分词前对文本进行处理,比如说html_strip分词器可以在分词前,先将文本进行去除html标签处理。内置分析器中没有使用过字符过滤器,不过我们可以使用字符过滤器在我们的自定义分析器中,ES提供的字符过滤器如下:

  • html_strip:去除 HTML 标签。
  • mapping:将字符或字符串替换为其他内容,支持自定义映射。
  • pattern_replace:使用正则表达式对字符或字符串进行替换。

4.2 分词器

无需多言,没有分词器怎么分词,ES提供分词器如下:

  • standard:默认的分词器,基于语言规则进行分词。
  • whitespace:按空格分词,不做进一步处理。
  • keyword:将整个输入文本视为一个词条,不进行分词,适用于精确匹配。
  • pattern:基于正则表达式分词,可以自定义分隔模式。
  • uax_url_email:适用于带有 URL 和电子邮件地址的文本的分词器。
  • ngram:基于字符的 n-gram 分词器,适合模糊匹配。
  • edge_ngram:基于字符的边界 n-gram 分词器,生成从开头的 n-gram,适合自动完成。
  • classic:类似 standard 分词器的旧版本,适用于英文文本。
  • letter:按字母字符分词,遇到非字母字符断开。
  • lowercase:转换为小写的 keyword 分词器,整个文本视为一个词条并小写化。
  • path_hierarchy:基于路径层级的分词器,适用于文件路径、URL 分级等。
  • char_group:按字符组分词,可以指定多个字符作为分隔符。

4.3 分词过滤器

分词过滤器是对分词后的索引再次进行处理,比如说当我们使用内置的standard分析器时,rm可以搜索到分词后的Rm索引,原因就是standard分析器使用了lowercase分词过滤器,ES提供的分词过滤器如下:

  • lowercase:将词条转换为小写。
  • uppercase:将词条转换为大写。
  • stop:去除停用词(例如 andthe),支持多种语言的停用词。
  • stemmer:词干提取器,将词条转换为词干(如 running 转为 run),支持多种语言。
  • asciifolding:将带重音符号的字符转换为 ASCII 字符(如 é 转为 e)。
  • synonym:替换同义词(如 quickfast 可以替换为彼此)。
  • shingle:生成包含多个词的组合(例如 New York 生成 New, York, New York),用于短语匹配。
  • ngram:基于词条的 n-gram,生成较小的词条,适合模糊匹配。
  • edge_ngram:基于词条的边界 n-gram,从词条开头生成较小的词条,适合自动完成。
  • unique:去除重复的词条。
  • reverse:将词条的字符顺序反转。
  • length:过滤指定长度范围外的词条。
  • truncate:将词条截断为指定长度。
  • porter_stem:使用 Porter 词干算法,提取英文词条的词干。
  • kstem:另一种英文词干算法,提取英文词条的词干。
  • snowball:使用 Snowball 词干算法,支持多种语言的词干提取。
  • fingerprint:为多词条生成指纹标识,去重并排序,适用于重复检测。
  • limit:限制词条数目,截断超出指定数量的词条。
  • pattern_capture:使用正则表达式捕获匹配模式的子部分。
  • pattern_replace:使用正则表达式替换词条内容。

ES并没有内置中文分词器,对于中文的分词我们可以使用IK分词器来实现。

我们可以进入IK的github地址,在下面的readme中提供了安装命令

bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/8.4.1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.4 自定义分析器

了解了分析器的三个部分后,我们就可以自由组合这三个部分,实现自己的自定义分析器,实例如下:

PUT my_index
{"settings": {"analysis": {"char_filter": {"mapping_filter": {"type": "mapping","mappings": ["$=>USD", "&=>and", "%=> percent"]}},"tokenizer": {"whitespace_tokenizer": {"type": "whitespace"}},"filter": {"lowercase_filter": {"type": "lowercase"},"english_stop_filter": {"type": "stop","stopwords": "_english_"}},"analyzer": {"my_custom_analyzer": {"type": "custom","char_filter": ["html_strip_filter""html_strip"],"tokenizer": "whitespace_tokenizer","filter": ["lowercase_filter", "english_stop_filter"]}}}}
}

实例中,我们在setting.analysis属性中,定义了字符过滤器mapping_filter,分词器whitespace_tokenizer,分词过滤器lowercase_filter和english_stop_filter。并将三者在analyzer中共同组合成了一个新的自定义分析器my_custom_analyzer。

像html_strip这种功能固定,无需配置的,可以直接放入自定义分析器中。

5. 词库

分析器功能虽然强大,不过其也是根据人类的语言习惯来进行分词,那么对于一些网络新型的热词,ES该如何分辨呢。这就涉及到更改词库的操作。

词库种类很多,不用的解析器能够使用的词库种类也不同(分词规则不同,词库当然也不同)。

比如说ES本身支持六种词库,包括:

  • 停用词库:用于过滤无意义的常见词。
  • 同义词库:用于归类同义词,增强召回率。
  • 词干提取词库:用于词态还原,统一不同词态。
  • 关键词映射词库:用于标准化关键术语。
  • 拼写纠正词库:用于修正拼写错误,提高搜索容错。
  • 停用词变体词库:适合特定领域的停用词。

而这六种词库,IK分析器能够识别的只有停用词库,同一词库,以及停用词变体词库。与其说IK只识别,倒不如说只有这三种词库对中文分词有帮助,所以不同的分析器,需要的词库也不同,完全根据分析器本身的性质来(ES内置的分析器也对这些词库的使用不完全兼容)。

具体操作

以停用词库为例,我们可以在自定义stop类型的分词过滤器时,给stopwords_path属性设置路径,示例如下:

PUT my_index
{"settings": {"analysis": {"filter": {"custom_stopwords": {"type": "stop","stopwords_path": "analysis/stopwords.txt"  // 指定停用词库文件路径}},"analyzer": {"my_analyzer": {"type": "custom","tokenizer": "standard","filter": ["lowercase", "custom_stopwords"]}}}}

这样ES就会去寻找conf/analysis/stopwords.txt文件中,读取其中的停用词信息(一行为一词)。

而对于IK分析器,其可以在配置文件中配置远程词库链接(就是一个txt文件的链接)实现远程词库,以及基于mysql的远程词库,这里就不多说了。

6. 聚合查询

聚合查询就是将大量数据结合在一起查询,获取一些公共的数据。ES中聚合查询分为三种,分别为桶聚合(Bucket Aggregation)度量聚合(Metric Aggregation)管道聚合(Pipeline Aggregation)

为了方便演示,我创建如下索引及数据

PUT products
{"mappings": {"properties": {"description": {"type": "text",},"category": {"type": "keyword"},"price": {"type": "float"},"rating": {"type": "integer"},"timestamp": {"type": "date"}}}
}
POST products/_bulk
{ "index": { "_id": 1 } }
{ "description": "高性能的Elasticsearch搜索引擎", "category": "电子产品", "price": 299.99, "rating": 4, "timestamp": "2023-01-10T12:00:00" }
{ "index": { "_id": 2 } }
{ "description": "Elasticsearch用于大数据分析", "category": "软件", "price": 199.99, "rating": 5, "timestamp": "2023-01-15T12:00:00" }
{ "index": { "_id": 3 } }
{ "description": "时尚服装,舒适体验", "category": "服装", "price": 49.99, "rating": 3, "timestamp": "2023-02-10T12:00:00" }
{ "index": { "_id": 4 } }
{ "description": "优质材料的服装", "category": "服装", "price": 79.99, "rating": 4, "timestamp": "2023-02-12T12:00:00" }
{ "index": { "_id": 5 } }
{ "description": "家用实木家具", "category": "家具", "price": 499.99, "rating": 5, "timestamp": "2023-03-01T12:00:00" }
{ "index": { "_id": 6 } }
{ "description": "现代风格的家具", "category": "家具", "price": 299.99, "rating": 3, "timestamp": "2023-03-05T12:00:00" }
{ "index": { "_id": 7 } }
{ "description": "智能家电,方便生活", "category": "家电", "price": 1200.00, "rating": 5, "timestamp": "2023-04-01T12:00:00" }
{ "index": { "_id": 8 } }
{ "description": "高效节能的家电", "category": "家电", "price": 850.00, "rating": 4, "timestamp": "2023-04-03T12:00:00" }
{ "index": { "_id": 9 } }
{ "description": "新鲜食品,健康选择", "category": "食品", "price": 15.00, "rating": 4, "timestamp": "2023-05-10T12:00:00" }
{ "index": { "_id": 10 } }
{ "description": "有机食品,绿色生活", "category": "食品", "price": 10.00, "rating": 3, "timestamp": "2023-05-12T12:00:00" }

6.1 桶聚合(Bucket Aggregation)

桶聚合就是将数据按照某个属性的的不同,进行分桶(其实就是简单的分类),实例如下:

在这里插入图片描述

查询方法就是通过/索引名/_search,然后请求体中的size:0是为了不展示查询的数据,只展示分桶数据。而aggs就是聚合查询的属性,在其中我们可以创建一个聚合类型的名称,这里我起的名称是bucket,其中terms代表的就是桶聚合,而field则是选择桶聚合的属性。

如图所示,结果是通过category属性将数据粉了六类,并标记了每个种类的数量。

对于text属性的桶聚合比较特殊。在创建索引时,映射中与属性类型同级的配置,还有一个fileddata,这个属性是用于对属性生成正排索引的,处text外,其他索引都支持精确查询,索引需要正排索引,所以这个值都是true。而text不支持精确搜索,其搜索功能依赖倒排索引,所以fileddata是false。但是分桶依赖的也是正排索引,所以text默认情况下并不支持分桶聚合,示例如下:

在这里插入图片描述

但是我们如果将fieldata设置为true呢,我们通过如下请求,将其设置为true:

POST products/_mapping
{"properties":{"description":{"type":"text",#类型必须在写一次,并且和原来一样"fielddata": true}}
}

在这里插入图片描述

可以看到,虽然分词成功了,但是结果很奇怪。实际上对text类型的分桶会根据分词后的结果进行分桶,而图中结果是因为ES内置的分词器不会对中文进行分词,所以结果就是一个字一个类。

而且数量也不够,这是因为与field属性平级的还有一个属性size,这个属性可以控制结果的数量,默认最多分为十个桶。

实际生产中如何设计text类型进行分桶的操作,通常是给其设置一个keyword类型的属性,然后通过对这个属性的分桶,来对text分桶,假设我们的description有一个tag属性,那么我们只需要在field属性中赋值description.tag即可。

6.2 度量聚合

度量聚合就是对数据进行计算,比如最大值,最小值,平均值等,具体如下

GET products/_search
{"size": 0,"aggs": {"average_price": {"avg": {"field": "price"}},"total_price": {"sum": {"field": "price"}},"max_price": {"max": {"field": "price"}},"min_price": {"min": {"field": "price"}},"price_count": {"value_count": {"field": "price"}}}
}

在这里插入图片描述

通过度量聚合可以对数据进行统计计算

6.3 管道聚合

管道聚合就是将一种聚合的结果,交给另一个聚合计算。

在这里插入图片描述

如图所示,可以在聚合的统计在写一个aggs,接受上一个聚合结果,也可以i通过buckets_path来指定路径。

6.4 将查询结果进行聚合查询

我们可以将query查询的结果,在使用aggs进行聚合查询,示例如下:

在这里插入图片描述

如图,我们将价格大于一百的产品拿出来,在进行分桶。

6.5 脚本查询

Elasticsearch 支持的脚本语言包括 Painless(默认和推荐),并支持 expressionmustache 等语言。下面我们重点介绍如何使用 Painless。我们可以在其script.source属性上编写查询脚本,示例如下:

在这里插入图片描述

图中第一个命令是以脚本作为条件,第二个是自己创建一个属性,用脚本计算值,并且支持传参。

7. 搜索推荐

在使用搜索引擎的搜索框时,当我们输入一部分文字,底部弹窗机会弹出我们可能想要搜索的东西,这个功能就是搜索推荐,搜索推荐的功能本质上也是通过输入的一部分,搜索全部部分,但是和搜索text类型文本不同的是,搜索推荐搜索的是分词后的倒排索引(也可以说是词库里的热词)返回给用户,方便用户进行搜索。

搜索推荐本质上也是搜索,是通过ES提供的suggest关键字实现的,其中包含一下四类实现

7.1 completion Suggester

功能completion suggester 是一种用于实现自动完成(autocomplete)的建议器。它基于轻量级的索引结构(FST,有限状态转换器),可以实现快速的前缀匹配,非常适合用于实时的搜索推荐。

常用参数

  • field:指定用于自动完成的字段(通常是 completion 类型的字段)。
  • prefix:用户输入的前缀,建议器将提供与该前缀匹配的推荐项。
  • size:控制返回的建议项数量。
  • fuzzy:用于启用模糊匹配(例如拼写错误时也能匹配),可以设置 fuzziness 参数来调整模糊匹配的程度。

示例

POST products/_search
{"suggest": {"product-suggest": {"prefix": "iph","completion": {"field": "suggest","size": 5,"fuzzy": {"fuzziness": 2}}}}
}

7.2 term Suggester

功能term suggester 用于拼写纠错,可以在用户输入有错字时推荐正确的词。它基于倒排索引,适合单个词的拼写纠错。

常用参数

  • field:指定拼写建议的字段。

  • text:用户输入的文本,建议器将对该文本进行拼写检查。

  • suggest_mode

    :指定建议模式,可以是:

    • missing:仅当词项缺失时才进行建议。
    • popular:仅对频率最高的词进行建议。
    • always:总是提供建议。
  • max_edits:指定允许的编辑距离(即拼写错误的字符数),默认为 2。

  • prefix_length:指定匹配前缀的最小长度,减少计算量。

  • size:控制返回的建议项数量。

示例

POST products/_search
{"suggest": {"text": "iphon","spellcheck-suggest": {"term": {"field": "name","suggest_mode": "always","max_edits": 1,"size": 3}}}
}

7.3 phrase Suggester

功能phrase suggester 用于长查询的拼写纠错,特别适合基于上下文的拼写建议。例如,当用户输入多个单词时,phrase suggester 可以利用上下文信息来提供更智能的拼写建议。

常用参数

  • field:指定用于建议的字段,一般设置为 text 字段。

  • text:用户输入的文本,建议器将检查其中的拼写和上下文。

  • size:控制返回的建议项数量。

  • gram_size:指定 n-gram 的大小,通常设置为 2 或 3,用于基于上下文生成的建议。

  • direct_generator

    :用于控制建议生成的方式,可以指定多个生成器,参数包括:

    • field:指定字段。
    • suggest_mode:建议模式,类似于 term suggester。
    • min_word_length:建议生成器适用的最小单词长度。
    • prefix_length:最小前缀长度。
    • size:每个生成器返回的建议项数量。
  • highlight:用于高亮拼写建议的部分,通常包含 pre_tagpost_tag 参数,用于包裹拼写建议的高亮标记。

示例

POST products/_search
{"suggest": {"text": "iphon apple","phrase-suggest": {"phrase": {"field": "name.trigram","size": 1,"gram_size": 3,"direct_generator": [{"field": "name","suggest_mode": "always","min_word_length": 3}],"highlight": {"pre_tag": "<em>","post_tag": "</em>"}}}}
}

7.4 context Suggester

功能context suggester 是 completion suggester 的扩展,用于在自动完成推荐中增加上下文信息的过滤。例如,可以根据地理位置、类别、时间等上下文条件来过滤建议项。

常用参数

  • field:指定 completion 类型的字段。

  • prefix:用户输入的前缀。

  • contexts

    :用于指定上下文条件,可以是地理位置、类别等。

    • location:可以指定一个地理位置范围,例如 { "lat": 40.71, "lon": -74.01 }
    • category:可以指定一个分类标签,例如 "electronics"

示例

POST products/_search
{"suggest": {"product-suggest": {"prefix": "iph","completion": {"field": "suggest","size": 5,"contexts": {"category": ["electronics"]}}}}
}
解释

在这个示例中,context 被设置为 category,只有符合 "electronics" 分类的建议项会被返回。

我们没办法讲所有命令全部记在脑子里,对于ES的学习,我们的目的也只是知道ES能干什么,大致有什么东西,对于实际的需求,还是需要在实际解决时搜索对应命令。除了文中给的指令外,ES的指令还有非常多,这里也不多介绍了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/15898.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C语言入门到精通(第六版)——第十六章

16、网络套接字编程 16.1、计算机网络基础 计算机网络技术是计算机技术和通信技术相结合的产物&#xff0c;代表计算机的一个重要发展方向。了解计算机的网络结构&#xff0c;有助于用户开发网络应用程序。 16.1.1、IP地址 为了使网络上的计算机能够彼此识别对方&#xff0c;…

Electron教程1-初学入门

玩转Electron Electron 是什么注意事项环境安装安装 vscode安装 git 第一个实例第二个实例第二个实例解读 总结问题解答 Electron 是什么 Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个…

柠乐音乐 1.3.87 | 界面优美支持无损音乐下载的音乐播放器

柠乐音乐app提供丰富的音乐资源&#xff0c;涵盖流行、摇滚、古典等多种类型音乐&#xff0c;并且全部免费。支持FLAC无损音质音乐免费高速下载。内置独特推荐算法&#xff0c;可根据用户喜好智能推荐音乐。还包括电台播放资源、歌单同步&#xff08;支持网易云音乐和QQ音乐&am…

【资料】网络安全风险评估报告,风险管理报告,网络安全风险管理计划,网络安全网络安全能力验证报(Word原件)

一、概述 1.1工作方法 1.2评估依据 1.3评估范围 1.4评估方法 1.5基本信息 二、资产分析 2.1 信息资产识别概述 2.2 信息资产识别 三、评估说明 3.1无线网络安全检查项目评估 3.2无线网络与系统安全评估 3.3 ip管理与补丁管理 3.4防火墙 四、威胁细类分析 4.1威胁…

change buffer:到底应该选择普通索引还是唯一索引

文章目录 引言第一章&#xff1a;普通索引和唯一索引在查询逻辑与效率上的对比1.1 查询逻辑分析1.2 查询效率对比 第二章&#xff1a;普通索引和唯一索引在更新逻辑与效率上的对比2.1 更新逻辑分析2.2 更新效率对比 第三章&#xff1a;底层原理详解 - 普通索引和唯一索引的区别…

软件工程师简历(精选篇)

【#软件工程师简历#】 一份专业而精准的软件工程师简历&#xff0c;不仅能够全面展示技术实力和项目经验&#xff0c;更是赢得理想工作机会的重要敲门砖。那么&#xff0c;如何撰写一份令人印象深刻的软件工程师简历呢&#xff1f;以下是幻主简历整理的软件工程师简历&#xf…

深度学习推荐系统的工程实现

参考自《深度学习推荐系统》——王喆&#xff0c;用于学习和记录。 介绍 之前章节主要从理论和算法层面介绍了推荐系统的关键思想。但算法和模型终究只是“好酒”&#xff0c;还需要用合适的“容器”盛载才能呈现出最好的味道&#xff0c;这里的“容器”指的就是实现推荐系统…

前缀和技巧解析

前缀和技巧解析 前缀和&#xff08;Prefix Sum&#xff09;是一种常用的算法技巧&#xff0c;用于高效地处理一系列连续子数组和的问题。通过构建一个额外的数组来存储从数组起始位置到当前位置的累计和&#xff0c;可以在常数时间内快速计算任意区间的和。 前缀和应用的典型…

(undone) MIT6.S081 2023 学习笔记 (Day4: LAB3 page tables)

LAB 网页&#xff1a;https://pdos.csail.mit.edu/6.S081/2023/labs/pgtbl.html 任务1&#xff1a;Speed up system calls 根据网页&#xff0c;操作系统可以通过把部分数据放入用户空间的页表&#xff0c;来使得部分系统调用不用进入内核空间&#xff0c;从而提高速度。我们的…

CSS:怎么把网站都变成灰色

当大家看到全站的内容都变成了灰色&#xff0c;包括按钮、图片等等。这时候我们可能会好奇这是怎么做到的呢&#xff1f; 有人会以为所有的内容都统一换了一个 CSS 样式&#xff0c;图片也全换成灰色的了&#xff0c;按钮等样式也统一换成了灰色样式。但你想想这个成本也太高了…

探索Python文档自动化的奥秘:`python-docx`库全解析

文章目录 探索Python文档自动化的奥秘&#xff1a;python-docx库全解析1. 背景&#xff1a;为何选择python-docx&#xff1f;2. python-docx是什么&#xff1f;3. 如何安装python-docx&#xff1f;4. 简单库函数使用方法创建文档添加段落添加标题添加表格插入图片 5. 应用场景自…

OCP证书如何下载?

访问Oracle CertView网站&#xff1a; 打开网址 https://certview.oracle.com/ &#xff0c;这是Oracle官方提供的证书查询平台 。 登录账号&#xff1a; 使用您的Oracle账号和密码登录CertView。如果您不记得密码&#xff0c;可以通过注册账号时预留的邮箱重置密码 。 查看成…

OBOO鸥柏“触摸屏广告一体机交互”亮相2024中国珠海航展

2024年11月12日&#xff0c;第十五届中国国际航空航天博览会&#xff08;简称中国航展或珠海航展&#xff09;在珠海拉开帷幕。展会现场&#xff0c;既有OBOO鸥柏一大批高精尖液晶显示产品集体亮相&#xff0c;也有航天相关科技领域及飞行表演队炫技蓝天等。在中国航展的各个科…

【智能分子动力学】深度学习驱动分子动力学方法概述

深度学习驱动分子动力学&#xff08;Deep Learning-driven Molecular Dynamics&#xff0c;简称DLDMD&#xff09;方法是将深度学习技术应用于分子动力学模拟中的一种创新方法。这种方法通过深度学习模型来提升传统分子动力学模拟的效率和精度&#xff0c;尤其是在复杂系统的建…

(69)基于Hilbert(希尔伯特)变换的调相信号解调的MATLAB仿真

文章目录 前言一、希尔伯特变换二、相位调制1.基本原理2.调制特点3.应用 三、使用希尔伯特变换进行相位解调的原理1. 解调原理2.算法优点 四、MATLAB仿真1. 仿真代码2. 仿真结果 总结 前言 本文首先介绍了相位调制技术&#xff0c;然后说明了使用希尔伯特变换进行调相信号解调…

ISUP协议视频平台EasyCVR视频设备轨迹回放平台智慧农业视频远程监控管理方案

在当今快速发展的农业领域&#xff0c;智慧农业已成为推动农业现代化、助力乡村全面振兴的新手段和新动能。随着信息技术的持续进步和城市化进程的加快&#xff0c;智慧农业对于监控安全和智能管理的需求日益增长。 视频设备轨迹回放平台EasyCVR作为智慧农业视频远程监控管理方…

Python——NumPy库的简单用法,超级详细教程使用

一、什么是NumPy库 NumPy&#xff1a;它是python的一个科学计算库函数&#xff0c;它是由c语言编写的 它应用于数据处理、机器学习、图像处理、文件操作等等 二、array函数 这里导入库numpy&#xff0c;命名为np&#xff0c;后面的np都是代表着是numpy函数 array函数表示创建…

【postman】怎么通过curl看请求报什么错

获取现成的curl方式&#xff1a; 1&#xff0c;拿别人给的curl 2&#xff0c;手机app界面通过charles抓包&#xff0c;点击接口复制curl 3&#xff0c;浏览器界面-开发者工具-选中接口复制curl 拿到curl之后打开postman&#xff0c;点击import&#xff0c;粘贴curl点击send&am…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(十三)图优化SLAM的本质

一、直白解释slam与图优化的结合 我从b站上学习理解的这个概念。 视频的大概位置是1个小时以后&#xff0c;在第75min到80min之间。图优化SLAM是怎么一回事。 slam本身是有运动方程的&#xff0c;也就是运动状态递推方程&#xff0c;也就是预测过程。通过t1时刻&#xff0c…

哔哩喵 2.3.11 | 非常好用的第三方B站客户端

哔哩喵是一款非常好用的第三方B站客户端&#xff0c;它允许用户查看各个分区在每个时间段的热门视频列表&#xff0c;支持关键字和UP主屏蔽功能&#xff0c;并能通过添加代理服务器来观看受地区限制的番剧。最新版本2.3.11更新了多项功能&#xff0c;包括个人中心头像及动态大图…