引言
在全文搜索引擎中,倒排索引是核心的数据结构,它通过从文档中提取关键词并建立关键词到文档的映射关系,实现了高效的文本检索。本文将详细介绍倒排索引的组成与作用,并结合 Elasticsearch,解析其索引、文档、字段等基本概念及常见字段类型,帮助您深入理解搜索引擎底层机制及数据建模方法。
什么是倒排索引?
倒排索引是全文搜索引擎的核心数据结构,其主要作用是从文档中提取关键词,并建立关键词到文档的映射关系。这种结构与传统的正排索引(即文档到关键词的映射)相反,因此称为倒排索引。
注:Elasticsearch 索引中,只有字符串类型字段会创建倒排索引。
倒排索引主要组成部分
词典中的每个词汇作为一个键,每个键对应一个倒排列表。
词典(Term Dictionary)
包含所有在文档集合中出现的词汇,是一个按字母顺序排序的列表,其中每个词条(term)都指向一个倒排列表。
倒排列表(Posting List)
对于词典中的每个词汇,倒排列表是与其相关联的列表,该列表包含出现在文档集合中的这个词的所有文档ID。倒排列表不仅仅包括文档ID,还包含词频(词在某个文档中出现的次数)、位置列表(可选,词在某个文档中的位置)、其它信息(词在标题或正文中的位置,词在文档中的重要性等)。
索引、类型、文档和字段
索引
索引存储具有相似特性文档的集合。相当于MySQL中的数据库。
类型
类型用于在同一个索引中将文档分类为不同类别。每个文档都有一个类型字段,指示其类别。从Elasticsearch 7.0版本开始,类型的概念被完全移除,一个索引只能包含一个类型。相当于MySQL中的表。
文档
文档是Elasticsearch中的基本信息单元,类似于关系型数据库中的一行数据。每个文档都有一个唯一的ID,并存储为JSON格式。相当于MySQL中的行数据。
字段
字段是文档中的属性或数据单元。每个字段都有一个名称和一个与之关联的值。相当于MySQL中的表字段。
字段类型
字符串类型
text:用于全文搜索的文本数据。text
类型的字段会被分词(tokenized)以便于搜索。
keyword:用于精确匹配的关键词数据。keyword
类型的字段不会被分词,常用于过滤、排序和聚合操作。
数值类型
integer:32位有符号整数。
long:64位有符号整数。
float:32位浮点数。
double:64位浮点数。
half_float:使用16位存储浮点数,节省存储空间,用于对精度要求不高的数据。
scaled_float:将浮点数乘以一个预定义的缩放因子(scaling_factor
)并存储为整数来提高数值存储的精度。这种方法在需要更高精度的十进制数表示时非常有用。下面示例是保存2位精度。
PUT /my_index
{
"mappings": {
"properties": {
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
布尔类型
boolean:用于表示true
或false
值。
日期类型
date:用于表示日期和时间。Elasticsearch支持多种日期格式。
复杂类型
object:用于表示嵌套的JSON对象结构,其内部字段会被扁平化(flatten)到顶层文档中。
nested:用于嵌套JSON对象,但它会将每个嵌套对象单独存储为一个隐藏的内部文档,从而保持嵌套关系的完整性。
#Json文档
{
"user": {
"name": "John",
"tags": [
{"key": "role", "value": "admin"},
{"key": "location", "value": "US"}
]
}
}
#使用object类型映射
PUT /my_index
{
"mappings": {
"properties": {
"user": {
"properties": {
"name": { "type": "text" },
"tags": {
"properties": {
"key": { "type": "keyword" },
"value": { "type": "text" }
}}}}}}}
#使用nested类型映射
PUT /my_index
{
"mappings": {
"properties": {
"user": {
"properties": {
"name": { "type": "text" },
"tags": {
"type": "nested",
"properties": {
"key": { "type": "keyword" },
"value": { "type": "text" }
}}}}}}}
#object类型搜索,将匹配任何包含user.tags.key为role且user.tags.value为admin的文档,
#但不考虑它们是否在同一个tags对象中。
GET /my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "user.tags.key": "role" } },
{ "match": { "user.tags.value": "admin" } }
]
}}}
#nested类型搜索,确保user.tags数组中同一个对象的key为role且value为admin的文档匹配。
GET /my_index/_search
{
"query": {
"nested": {
"path": "user.tags",
"query": {
"bool": {
"must": [
{ "match": { "user.tags.key": "role" } },
{ "match": { "user.tags.value": "admin" } }
]
}}}}}
地理类型
geo_point:用于表示地理空间中的一个点,即一个经纬度坐标。这个类型适合用来存储和查询简单的点数据,例如用户位置、商店位置等。
geo_shape:用于表示复杂的地理空间图形,如多边形、线、点集合等。这个类型适合用来存储和查询复杂的地理空间数据,例如国家边界、多边形区域等。
感谢您的阅读!如果文章中有任何问题或不足之处,欢迎及时指出,您的反馈将帮助我不断改进与完善。期待与您共同探讨技术,共同进步!