> 文章列表 > elasticsearch 其他字段类型详解和范例

elasticsearch 其他字段类型详解和范例

elasticsearch 其他字段类型详解和范例

本章主要内容

  • elasticsearch 中别名字段的详解和范例
  • elasticsearch 中二进制类型的详解和范例
  • elasticsearch 中的嵌套类型的详解和范例
  • elasticsearch 中的范围类型的详解和范例
  • elasticsearch 中的排名类型的详解和范例
  • elasticsearch 中的ip类型的详解和范例
  • elasticsearch 中的search-as-you-type 类型 的详解和范例
  • elasticsearch 中的token_count 类型 的详解和范例

概要

本篇文章主要讲解elasticsearch在业务中经常用到的字段类型,通过大量的范例来学习和理解不同字段类型的应用场景。范例elasticsearch使用的版本为7.17.5。

简述

在Elasticsearch的映射关系中,每个字段都对应一个数据类型或者字段类型,这些类型规范了字段存储的值和用途。

内容

elasticsearch 中别名字段的详解

  • alias(别名)类型可以为索引中的字段定义一个替代名称。

elasticsearch 中别名字段的范例

#创建名为userinfo的索引库并为其创建映射关系
PUT userinfo
{"mappings": {"properties": {"age": {"type": "long"},"aliasage": {"type": "alias","path": "age"},"transit_mode": {"type": "keyword"}}}
}
  • 这是一个创建名为"userinfo"的索引的请求。该索引定义了三个字段:
    • "age"字段,它是一个长整型字段。它存储用户的年龄信息。
    • "aliasage"字段,它是一个别名类型的字段。它通过指定"age"字段的路径作为别名的路径,将"aliasage"字段与"age"字段关联在一起。这样,对"aliasage"字段的搜索、聚合和排序操作将与对"age"字段进行的操作一样。
    • "transit_mode"字段,它是一个关键字类型的字段。它存储用户的交通方式信息。
#以上语句创建了userinfo索引库,而且为age字段创建了名为aliasage的别名。
#在索引库userinfo中插入一条文档数据
PUT userinfo/_doc/1
{"age": 39,"transit_mode": "transit_mode"
}#通过年龄查询大于30的用户信息
GET userinfo/_doc/_search
{"query": {"range": {"age": {"gte": 30}}}
}#通过别名查询年龄大于30的用户信息
GET userinfo/_doc/_search
{"query": {"range": {"aliasage": {"gte": 30}}}
}#通过年龄、别名查询返回的结果信息如下
{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "userinfo","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"age" : 39,"transit_mode" : "transit_mode"}}]}
}
  • 需要注意的是,别名字段只能作为查询的目标,而不能作为源字段。也就是说,你不能将文档数据写入"aliasage"字段,只能写入"age"字段。另外,别名的路径也必须指向实际存在的字段。如果路径指向的字段不存在,则会发生错误。

elasticsearch 中二进制类型的详解

  • 在 Elasticsearch 中,二进制字段的数据必须是 Base64 编码的字符串。这是因为 Elasticsearch 使用 JSON 作为其数据交换格式,而 JSON 不支持原始二进制数据。通过将二进制数据转换为 Base64 编码的字符串,可以确保数据在传输过程中不会出现问题。
  • 在 Elasticsearch 中,二进制类型(binary)用于存储和检索原始的二进制数据。通常情况下,Elasticsearch 主要用于处理结构化或半结构化的文本数据,但在某些场景下,您可能需要处理二进制数据,例如图片、音频、视频或其他非文本数据。在这种情况下,您可以使用二进制类型将这些数据存储在 Elasticsearch 中。

elasticsearch 中二进制类型的范例

#创建索引映射并指定blob字段的类型为二进制类型
PUT myindex-2_02
{"mappings": {"properties": {"name": {"type": "text"},"blob": {"type": "binary"}}}
}#在索引库中插入数据,blob的内容是Base64编码的字符串
PUT myindex-2_02/_doc/1
{"name":"Some binary blob","blob":"c2FkZw=="
}
  • 需要注意的是,二进制类型字段不支持全文搜索功能,因为这些字段存储的数据通常不是文本数据。此外,在处理大量的二进制数据时,Elasticsearch 的性能可能会受到影响。因此,在使用二进制类型时,请确保您了解其限制,并确保 Elasticsearch 适用于您的用例。
  • 最后,请记住,Elasticsearch 不是专门针对存储和检索大量二进制数据而设计的。根据您的需求,您可能需要评估其他数据存储解决方案(如分布式文件系统或对象存储),这些解决方案可能更适合处理大量二进制数据。在这种情况下,您可以将 Elasticsearch 用于存储和搜索元数据,而将实际的二进制数据存储在其他系统中。

elasticsearch 中的嵌套类型的详解

  • 嵌套类型用于在 Elasticsearch 文档中表示对象数组,它允许您对数组中的对象进行独立查询和过滤。这是处理具有父子关系或层次结构的数据非常有用的方法。

elasticsearch 中的嵌套类型的范例

  • 定义嵌套类型:在 Elasticsearch 的映射中,通过将字段类型设置为 "nested",可以定义嵌套类型
#创建索引映射并指定user字段为一个嵌套类型
PUT myindex-2_07
{"mappings": {"properties": {"user":{"type": "nested"}}}
}
  • 索引嵌套文档:使用嵌套类型时,可以将多个对象作为数组索引到 Elasticsearch 中。
#在索引库中插入文档数据,user字段中嵌套了键值对
PUT myindex-2_07/_doc/1
{"group": "fans","user": [{"first": "John","last": "Smith"},{"first": "Alice","last": "White"}]
}
  • 查询嵌套文档:要查询嵌套文档,需要使用 "nested" 查询。
#查询user索引库字段中user.first的值是Alice以及User.last的值是Smith的结果
GET myindex-2_07/_search
{"query": {"nested": {"path": "user","query": {"bool": {"must": [{"match": {"user.first": "Alice"}},{"match": {"user.last": "Smith"}}]}}}}
}
  • 以上查询语句中需要注意的是,利用嵌套字段进行筛选查询时,必须两个字段值都要符合条件,如果其中一个字段值不满足查询条件,则从索引库中查询不到任何数据,执行结果如图所示:

  • 嵌套类型在处理具有复杂关系的文档时非常有用。使用嵌套类型,可以在 Elasticsearch 中更有效地查询和过滤对象数组,并获取所需的详细信息。

elasticsearch 中的范围类型的详解

  • 范围类型 (range type) 是 Elasticsearch 中一种特殊的字段类型,它可以表示一个连续的范围或间隔.
  • range(范围)类型表示介于上限和下限之间的连续值范围,可以使用运算符gt(大于)、gte(大于等于)、lt(小于)、lte(小于等于)定义存储文档的数据范围。每一种范围类型的说明表如下:

范围类型

说明

integer_range

表示由符号的32位整数

float_range

表示单精度浮点数

long_range

表示有符号的64位整数

double_range

表示双精度浮点数

date_range

表示日期范围,可以通过format映射参数支持各种日期格式。无论使用哪种格式,日期值都会被解析为一个无符号的64位整数,该整数为纪元以来的毫秒数。

ip_range

表示IPv4或IPv6地址的一系列IP值

  • 范围类型的主要应用场景是对某个范围内的值进行查询和过滤。例如,查找生产日期在特定日期范围内的商品,或者查找价格在特定范围内的房屋等。

elasticsearch 中的范围类型的范例

#创建索引映射,并指定expected_attendees字段类型为整数范围类型,time_frame字段类型为日期范围类型
PUT myindex-2_08
{"mappings": {"properties": {"expected_attendees": {"type": "integer_range"},"time_frame":{"type": "date_range","format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}}}
}#插入文档数据
PUT myindex-2_08/_doc/1?refresh
{"expected_attendees":{"gte":10,"lt":20},"time_frame":{"gte":"2021-10-31 12:00:00","lte":"2021-11-01"}
}
  • 查询满足expected_attendees字段中数据范围内包含12的文档数据
GET myindex-2_08/_search
{"query": {"term": {"expected_attendees": {"value": "12"}}}
}

  • 根据日期范围查询符合条件的文档数据
#根据日期范围查询符合条件的文档数据
GET myindex-2_08/_search
{"query": {"range": {"time_frame": {"gte": "2021-10-31","lte": "2021-11-01","relation": "within"}}}
}

  • 由以上结果可知,只要范围类型字段的内容包含在筛选的范围内,就会返回当前文档的内容。
  • 总之,Elasticsearch 中的范围类型提供了对连续范围或间隔的查询和过滤功能,支持整数、长整数、浮点数、双精度浮点数、日期和 IP 地址等多种数据类型。这使得在特定范围内对数据进行筛选和分析变得更加简单和高效。

elasticsearch 中的排名类型的详解

  • rank_feature(排名)类型的字段可以存储数字,并且对搜索文档的分数有所影响(搜索文档的分数就是用户搜索的内容和搜索返回文档的匹配度,分数越高,就表示匹配度越高)
  • 这种字段类型在特定场景下非常有用,例如,当您需要根据某些特征对文档进行排序时。例如,电商网站中的产品排名,根据销量、评价等特征对产品进行排序。
  • rank_feature 字段的主要优势在于它可以在查询时高效地为文档评分。Elasticsearch 会在索引时预先计算相关的评分数据,从而加快查询性能。

elasticsearch 中的排名类型的范例

#创建索引映射并将"pagerank"和"topics"这两个字段类型分别指定为"rank_feature"类型和"rank_features"类型
PUT myindex-2_10
{"mappings": {"properties": {"pagerank":{"type": "rank_feature"},"url_length":{"type": "rank_feature","positive_score_impact":false},"topics":{"type": "rank_features"}}}
}#在索引库中插入数据
PUT myindex-2_10/_doc/1
{"url": "http://en.wikipedia.org/wiki/2016_Summer_Olympics","content": "Rio 2016","pagerank": 50.3,"url_length": 42,"topics": {"sports": 50,"brazil": 30}
}#在索引库中插入数据
PUT myindex-2_10/_doc/2
{"url": "http://en.wikipedia.org/wiki/2016_Brazilian_Grand_Prix","content": "Formula One motor race held on 13 November 2016 at the Autodromo Jose Carlos Pace in Sao Paulo,Brazil","pagerank": 50.3,"url_length": 47,"topics": {"sports": 50,"brazil": 20,"formula one":65}
}#在索引库中插入数据
PUT myindex-2_10/_doc/3
{"url": "http://en.wikipedia.org/wiki/Deadpool_(film)","content": "Deadpool is a 2016 American superhero film","pagerank": 50.3,"url_length": 37,"topics": {"movies":60,"super hero":65}
}#查询索引库的content字段值中包含"2016"的文档,并根据评分(score字段的值)排序输出
GET myindex-2_10/_search
{"query": {"bool": {"must": [{"match": {"content": "2016"}}],"should": [{"rank_feature": {"field": "pagerank"}},{"rank_feature": {"field": "url_length","boost": 0.1}},{"rank_feature": {"field": "topics.sports","boost": 0.4}}]}}
}
  • 返回的查询结果如图:

  • 由以上语句可知,rank_feature字段类型和rank_feaures字段类型只能搭配rank_feature参数进行查询。

elasticsearch 中的ip类型的详解

  • IP 类型用于存储和搜索 IPv4 和 IPv6 地址。它允许您高效地索引和查询 IP 地址数据,因此在处理网络日志、安全分析等场景时非常有用。
  • IP 类型的字段定义如下:
{"mappings": {"properties": {"ip_field": {"type": "ip"}}}
}

elasticsearch 中的ip类型的范例

  • 存储和查询 IPv4 和 IPv6 地址。Elasticsearch 可以处理 IPv4 和 IPv6 地址。
PUT my-index/_doc/1
{"ip_field": "192.168.1.1"
}PUT my-index/_doc/2
{"ip_field": "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
}
  • 范围查询。您可以使用范围查询来查找特定 IP 地址范围内的文档。
GET my-index/_search
{"query": {"range": {"ip_field": {"gte": "192.168.1.1","lte": "192.168.1.10"}}}
}
  • CIDR 符号。您还可以使用 CIDR 符号来查询特定子网内的 IP 地址。
GET my-index/_search
{"query": {"term": {"ip_field": "192.168.1.0/24"}}
}
  • 排序和聚合。Elasticsearch 允许您根据 IP 地址对结果进行排序和聚合。
GET my-index/_search
{"sort": [{"ip_field": {"order": "asc"}}]
}
  • 注意事项:
    • IP 类型只能用于存储 IP 地址。不要将其用于其他类型的数据。
    • 如果您的数据包含可能包含非 IP 地址的字符串,请在索引之前进行清理或使用关键字类型进行索引。
  • 总之,Elasticsearch 中的 IP 类型为处理 IP 地址数据提供了丰富的功能,使得在网络分析、安全监控等场景中非常实用。

elasticsearch 中的search-as-you-type 类型 的详解

  • search_as_you_type字段类型和text字段类型很相似,Elasticsearch对其进行了优化,为用户提供了开箱即用的功能。search_as_you_type字段类型的字段可以创建一系列的子字段
  • Search-as-you-type 是 Elasticsearch 中的一种特殊字段类型,用于实现实时的、基于部分输入的搜索建议功能。这种类型通过对输入的数据进行分析和索引,使得用户在输入查询的过程中就能看到相关的搜索建议。
  • search-as-you-type 字段类型的主要特点如下:
    • 分词器(Tokenizer)和分析器(Analyzer):为了实现部分匹配,search-as-you-type 字段类型使用了一种特殊的分词器和分析器。它们能够将输入的文本划分为多个递增的令牌(token),从而实现部分匹配。这些令牌会被存储在倒排索引中,以便在搜索时匹配。
    • 边缘 N-gram:为了提高搜索建议的相关性,search-as-you-type 字段类型使用了边缘 N-gram 技术。这种技术可以将输入的文本切分成一个个递增的子字符串,从而在搜索时能够实现部分匹配。这对于处理拼写错误、缩写或其他输入不完整的情况非常有用。
    • 实时性:search-as-you-type 字段类型提供了实时的搜索建议功能,这意味着当用户输入查询时,系统会立即返回与部分输入匹配的建议。这种实时性可以帮助用户更快地找到他们想要的信息,提高搜索体验。

elasticsearch 中的search-as-you-type 类型 的范例

  • 为了使用 search-as-you-type 字段类型,你需要在映射(mapping)中定义该字段。例如:
{"mappings": {"properties": {"title": {"type": "search_as_you_type"}}}
}
  • 当执行下面的映射模板时,将会为my_field字段创建下表中的所有字段作为其子字段。

创建的字段

说明

my_field

按照映射中的配置进行分析,如果未配置分词器,则使用索引的默认分词器

my_field._2gram

用大小为2的shingle token filter 分词器对 ny_field进行分词

my_field._3gram

用大小为3的shingle token filter 分词器对 ny_field进行分词

my_field._index_prefix

用edge ngram token filter 打包 my_field._3gram的分词器

  • 在这个例子中,我们为文档的 "title" 字段定义了 search-as-you-type 类型。之后,在索引文档时,Elasticsearch 会自动使用相应的分析器和分词器处理该字段。
  • 当你要查询 search-as-you-type 字段时,可以使用 "multi_match" 查询类型,并指定 "type" 为 "bool_prefix"。例如:
{"query": {"multi_match": {"query": "search text","type": "bool_prefix","fields": ["title","title._2gram","title._3gram"]}}
}
  • 这个查询会在 "title" 字段及其 N-gram 子字段上执行部分匹配查询,返回与输入文本匹配的文档。这样,用户就可以在输入过程中获得相关的搜索建议。
  • 总之,search-as-you-type 字段类型是 Elasticsearch 中一种实现实时搜索建议功能的有效方式。通过使用特殊的分词器

elasticsearch 中的token_count 类型 的详解

  • token_count(令牌计数)类型的字段实际上是一个integer类型字段,它可以对内容进行分词分析,存储内容被分词的数量
  • 用途:token_count 类型用于计算给定文本中的词元数量。它通常与 text 类型字段一起使用,因为这些字段包含实际的文本数据。
  • 分析器:您可以为 token_count 类型指定一个分析器。分析器负责将文本拆分为词元。在默认情况下,Elasticsearch 使用标准分析器。如果需要,可以自定义分析器来满足特定的需求。
  • 需要注意的是,token_count 类型不适用于全文搜索,而主要用于过滤、排序和聚合操作。此外,词元数量不会随着文本的变化而更新,因此,如果文本内容发生更改,需要重新索引文档以更新词元计数。

elasticsearch 中的token_count 类型 的范例

#创建索引映射,给name字段添加子对象,其名称是length,类型是token_count,使用standard分词器进行分词
PUT myindex-tokencount
{"mappings": {"properties": {"name":{"type": "text", "fields": {"length":{"type":"token_count","analyzer":"standard"}}}}}
}#添加文档数据
PUT myindex-tokencount/_doc/1
{"name":"John Smith"
}#添加文档数据
PUT myindex-tokencount/_doc/2?pretty
{"name":"Rachel Alice Williams"
}PUT myindex-tokencount/_doc/3
{"name":"长大"
}#查询索引库中name字段被分词后,分词的数量等于2的文档
GET myindex-tokencount/_search
{"query": {"term": {"name.length": {"value": "2"}}}
}

  • 可以看到"John Smith"被standard分词为"John"和"Smith",所以分词数量是2。上面的返回结果符合预期。在查询过程中,我们还可以使用分析语句对查询的内容进行预判分析,范例如下:
#使用standard分词器对内容"John Smith"进行分词处理,返回分词后的结果
GET myindex-tokencount/_analyze
{"analyzer": "standard","text":["John Smith"]
}

  • 以上结果与我们预想的一样,"Joh Smith"被分词成两个单词,还记录了具体分词的单词在原始内容的偏移量。