Elasticsearch 通关教程(二): 索引映射Mapping问题

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 数据库建表的时候,我们的DDL语句一般都会指定每个字段的存储类型,例如:varchar,int,datetime等等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱。CREATE TABLE `shop_` ( `id_` varchar(36) NOT NULL COMMENT '...

数据库建表的时候,我们的DDL语句一般都会指定每个字段的存储类型,例如:varchar,int,datetime等等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱。

CREATE TABLE `shop_` (
  `id_` varchar(36) NOT NULL COMMENT 'id',
  `shop_name_` varchar(50) DEFAULT NULL COMMENT '商品名称',
  `shop_integral_` int(11) DEFAULT NULL COMMENT '兑换所需积分',
  `shop_money_` decimal(10,0) DEFAULT NULL COMMENT '劵面金额',
  `start_time_` datetime DEFAULT NULL COMMENT '有效开始时间',
  `end_time_` datetime DEFAULT NULL COMMENT '有效结束时间',
  `is_delete_` int(1) DEFAULT '1' COMMENT '是否删除-1:有效,0:删除',
  PRIMARY KEY (`id_`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

在 Elasticsearch中也是这样,创建索引的时候一般也需要指定索引的字段类型,这种方式成为映射(Mapping)。

字段类型

映射(Mapping)针对的是文档的字段,数据库中有varchar,int,datetime等数据类型,那么我们ElasticSearch中又有哪些字段类型,每个字段类型都代表什么意思呢?

ElasticSearch更新频繁,以下内容是针对6.x版本的,对于5.x版本以及之前的版本可能有所不同,未来7.x版本也许也会有所改变,本篇不能做到面面俱到,所以大家可以针对自己的版本查阅官方文档。

Elasticsearch支持文档字段的多种不同数据类型,根据官方文档的分类,可以划分为以下几个类别:
核心数据类型复杂数据类型Geo(地理)数据类型专用数据类型多字段

核心数据类型

  • 字符串类型
    主要包括:text 和 keyword。
  • 数字类型
    主要包括:long, integer, short, byte, double, float, half_float, scaled_float
  • 日期类型
  • 布尔类型
  • 二进制类型
  • 范围数据类型
    integer_range, float_range, long_range, double_range, date_range

这里我们重点介绍下 text 和 keyword 的区别:

text 用于索引全文值的字段,例如电子邮件正文或产品说明。这些字段是analyzed,它们通过分词器传递 ,以在被索引之前将字符串转换为单个术语的列表。分析过程允许Elasticsearch搜索单个单词中 每个完整的文本字段。文本字段不用于排序,很少用于聚合(尽管 重要的文本聚合 是一个值得注意的例外)。

keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们通常用于过滤,排序,和聚合。keyword字段只能按其确切值进行搜索。如果您需要索引电子邮件正文或产品说明等全文内容,则可能应该使用text字段。

有时候一个字段同时拥有全文类型(text)和关键字类型(keyword)是有用的:一个用于全文搜索,另一个用于聚合和排序。这可以通过多字段类型来实现。

复杂数据类型

Geo数据类型

专用数据类型

多字段

有时候单纯的一个字段类型满足不了我们复杂的需求,为了不同的目的,以不同的方式索引同一个字段通常很有用。多字段也是ES的一种数据类型,只不过结合了更多的功能。

例如,对于字符串字段,我们既可以将它映射为text类型用于全文搜索,亦可以将它映射为keyword类型用于排序或聚合,或者,还可以使用标准分词器、英语分词器和其他语言分词器索引文本字段。

大多数数据类型都通过fields参数支持多字段。例如对于城市名称的多字段映射,可以这样写:

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "cityName": {
          "type": "text",
          "fields": {
            "raw": { 
              "type":  "keyword"
            }
          }
        }
      }
    }
  }
}

Elasticsearch的字段类型讲解完了,我们接下来正式介绍 ES的映射,ES是如何将索引文档和数据类型进行关联的,创建索引前是否必须制定索引文档的数据类型呢?

映射

映射是定义一个文档及其包含的字段如何存储和索引的过程。例如,使用映射来定义:

  • 应将哪些字符串字段视为全文字段。
  • 哪些字段包含数字,日期或地理位置。
  • 是否应将文档中所有字段的值索引到catch-all _all字段中。
  • 日期值的格式。
  • 自定义规则以控制动态添加字段的映射。

其实在 ElasticSearch中可以不需要事先定义映射(Mapping),文档写入ElasticSearch时,会根据文档字段自动识别类型,但是通过这种自动识别的字段不是很精确,对于一些复杂的需要分词的就不适合了。

根据是否自动识别映射类型,我们可以将映射分为动态映射静态映射

动态映射,即不事先指定映射类型(Mapping),文档写入ElasticSearch时,ES会根据文档字段自动识别类型,这种机制称之为动态映射。

静态映射,即人为事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为静态映射,亦可称为显式映射。

动态映射

Elasticsearch最重要的功能之一是它试图摆脱你的方式,让你尽快开始探索你的数据。Elasticsearch试图让你成功安装环境之后就可以直接使用。要索引文档,您不必首先创建索引、定义映射类型和定义字段,其实您只需索引一个文档数据,然后索引、类型和字段将自动生效。

索引一个图书的文档:

PUT /library/book/1
{
  "bookId":1,
  "bookName":"Java核心技术 卷I",
  "publishDate":"2014-03-12"
}

返回结果如下,表示成功

{
  "_index": "library",
  "_type": "book",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

我们看下mapping映射信息

GET library/_mapping

得到如下映射信息,重点关注mapping节点的内容

{
  "library": {
    "mappings": {
      "book": {
        "properties": {
          "bookId": {
            "type": "long"
          },
          "bookName": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "publishDate": {
            "type": "date"
          }
        }
      }
    }
  }
}

可以看到,我们并没有创建索引映射,Elasticsearch自动根据文档数据为我们映射了字段类型,bookId的映射类型为long,bookName的映射类型为多字段的即为text,同时也为keyword,publishDate的映射类型为date。可以看到ES的动态映射功能还是蛮强大的。

默认情况下,当在文档中找到以前未见过的字段时,Elasticsearch会自动将这个新字段添加到类型映射中。我们可以在文档和object级别禁用这项功能,具体操作方式就是通过将dynamic参数设置为falsestrict设为false是忽略新字段,而设为strict是如果遇到未知字段,就抛出异常

假设启用了动态字段映射功能,则使用一些简单的规则来确定字段应具有的数据类型:

JSON datatype Elasticsearch datatype
null 没有字段添加
true or false boolean
integer long
object object
array 依赖于数组中首个非空值
string 可以是日期字段、double或long字段,也可以是带有关键字子字段的文本字段。

上面这些是可以动态检测到的字段数据类型,而其他的以外的字段必须要显式映射数据类型了。

对于string字符串字段,动态映射的结果会有多种,可能映射为日期类型,也可能映射为double或long类型,也可能映射为带有关键字的text类型,具体结果要看配置的检测类型,是日期检测还是数字检测。

日期检测
如果date_detection启用(默认),则检查新字符串字段以查看其内容是否与dynamic_date_formats指定的任何日期模式匹配 。如果找到匹配项,那么则添加为具有对应格式的date新字段。

默认值为

dynamic_date_formats:[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]

例如:

PUT my_index/_doc/1
{
  "create_date": "2015/09/02"
}

通过GET my_index/_mapping得到的结果为:

{
  "my_index": {
    "mappings": {
      "_doc": {
        "properties": {
          "city": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "create_date": {
            "type": "date",
            "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
          }
        }
      }
    }
  }
}

动态日期检测可以通过设置date_detectionfalse来禁用:

PUT my_index
{
  "mappings": {
    "_doc": {
      "date_detection": false
    }
  }
}

PUT my_index/_doc/1 
{
  "create": "2015/09/02"
}

禁用之后,重新获取映射类型,得到如下结果:

{
  "my_index": {
    "mappings": {
      "_doc": {
        "date_detection": false,
        "properties": {
          "create": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

这时,create_date字段已被添加为文本字段。我们也可以自定义检测到的日期格式,通过dynamic_date_formats可以自定义以支持您自己的日期格式:

PUT my_index 
{ 
  "mappings":{ 
    "_ doc":{ 
      "dynamic_date_formats":["MM / dd / yyyy"] 
    } 
  } 
} 

数字检测
虽然JSON支持本机浮点和整数数据类型,但某些应用程序或语言有时可能将数字呈现为字符串。通常,正确的解决方案是显式映射这些字段,但可以启用数字检测(默认情况下禁用)以自动执行此操作:

PUT my_index 
{ 
  "mappings":{ 
    "_ doc":{ 
      "numeric_detection":true 
    } 
  } 
} 

PUT my_index / _doc / 1 
{ 
  "my_float":"1.0",
  "my_integer":"1" 
}

其中my_float字段将添加为float字段,my_integer字段将添加为long字段。

除了上面列出的选项外,还可以进一步自定义动态字段映射规则dynamic_templates,动态模板允许您定义可应用于动态添加字段的自定义映射,具体取决于:

  • Elasticsearch检测到 的数据类型match_mapping_type。
  • 字段的名称,带match和unmatch或match_pattern。
  • 字段的完整虚线路径,带path_match和path_unmatch。

更多具体内容可参考官方文档,Dynamic templates一章这里就不多叙述了。

静态映射(显式映射)

动态映射的自动类型推测功能并不是100%正确的,这就需要静态映射机制。静态映射与关系数据库中创建表语句类型,需要事先指定字段类型。相对于动态映射,静态映射可以添加更加详细字段类型、更精准的配置信息等。

既然可以自定义映射字段类型,那么那些复杂的字段类型和分词器我们都可以根据自己需求添加了,以提供了字段映射使用的各种映射参数的详细说明,这些映射参数对于某些或所有字段数据类型是通用的,内容太多,这里感兴趣的读者可以点击具体链接阅读。

映射参数 说明
analyzer 分析器
normalizer 在 Elasticsearch 中处理字符串类型的数据时,如果我们想把整个字符串作为一个完整的 term 存储,我们通常会将其类型 type 设定为 keyword。但有时这种设定又会给我们带来麻烦,比如同一个数据再写入时由于没有做好清洗,导致大小写不一致,比如 apple、Apple两个实际都是 apple,但当我们去搜索 apple时却无法返回 Apple的文档。要解决这个问题,就需要 Normalizer出场了。
boost 单个字段可以自动提升以计数更多的相关性得分
coerce 强制尝试清除脏值以适合字段的数据类型。数据并不总是干净的,根据它的生成方式,数字可能会在JSON正文中呈现为真正的JSON数字,例如5,但它也可能呈现为字符串,例如"5"。或者,应该是整数的数字可以替代地呈现为浮点,例如5.0,或甚至 "5.0"。
copy_to copy_to参数允许您创建自定义 _all字段,可以将多个字段的值复制到组字段中,然后可以将其作为单个字段进行查询。
doc_values
dynamic 设置动态映射
enabled enabled设置只能应用于映射类型和 object字段,导致Elasticsearch完全跳过对字段内容的解析
fielddata
eager_global_ordinals
format 格式化日期
ignore_above
ignore_malformed
index_options
index
fields
norms
null_value 当字段设置为null,(或空数组或null值数组)时,它被视为该字段没有值。不能被索引或搜索
position_increment_gap
properties
search_analyzer
similarity
store
term_vector
相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
21天前
|
存储 API 数据库
检索服务elasticsearch索引(Index)
【8月更文挑战第23天】
36 6
|
4天前
|
JSON 自然语言处理 数据库
ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入
概念、ik分词器、倒排索引、索引和文档的增删改查、RestClient对索引和文档的增删改查
ElasticSearch基础1——索引和文档。Kibana,RestClient操作索引和文档+黑马旅游ES库导入
|
14天前
|
存储 搜索推荐 数据建模
Elasticsearch 的数据建模与索引设计
【9月更文第3天】Elasticsearch 是一个基于 Lucene 的搜索引擎,广泛应用于全文检索、数据分析等领域。为了确保 Elasticsearch 的高效运行,合理的数据建模和索引设计至关重要。本文将探讨如何为不同的应用场景设计高效的索引结构,并分享一些数据建模的最佳实践。
35 2
|
1月前
|
存储 运维 搜索推荐
运维开发.索引引擎ElasticSearch.倒序索引的概念
运维开发.索引引擎ElasticSearch.倒序索引的概念
37 1
|
29天前
|
JSON 自然语言处理 数据库
Elasticsearch从入门到项目部署 安装 分词器 索引库操作
这篇文章详细介绍了Elasticsearch的基本概念、倒排索引原理、安装部署、IK分词器的使用,以及如何在Elasticsearch中进行索引库的CRUD操作,旨在帮助读者从入门到项目部署全面掌握Elasticsearch的使用。
|
1月前
|
自然语言处理 Java 索引
ElasticSearch 实现分词全文检索 - Java SpringBoot ES 索引操作
ElasticSearch 实现分词全文检索 - Java SpringBoot ES 索引操作
31 0
|
1月前
|
运维 安全 网络协议
运维.索引引擎ElasticSearch.记录一个小异常:received plaintext http traffic on an https channel
运维.索引引擎ElasticSearch.记录一个小异常:received plaintext http traffic on an https channel
99 0
|
14天前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
29天前
|
数据可视化 Docker 容器
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
这篇文章提供了通过Docker安装Elasticsearch和Kibana的详细过程和图解,包括下载镜像、创建和启动容器、处理可能遇到的启动失败情况(如权限不足和配置文件错误)、测试Elasticsearch和Kibana的连接,以及解决空间不足的问题。文章还特别指出了配置文件中空格的重要性以及环境变量中字母大小写的问题。
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
|
1月前
|
Ubuntu Oracle Java
如何在 Ubuntu VPS 上安装 Elasticsearch
如何在 Ubuntu VPS 上安装 Elasticsearch
15 0