ElasticSearch之index type mapping

2021-11-22 09:50:21 浏览数 (1)

生活中的数据总体上可以分为两种:

结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。指具有固定格式或有限长度的数据,如数据库,元数据等。

非结构化数据:又可称为全文数据,不定长或无固定格式,不适于由数据库二维表来表现,包括所有格式的办公文档、XML、HTML、Word 文档,邮件,各类报表、图片和音频、视频信息等。

说明:如果要更细致区分的话,XML、HTML 可划分为半结构化数据。因为它们也具有自己特定的标签格式,所以既可以根据需要按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。

对于这两种数据分类,搜索也相应分为两种:

结构化数据搜索:因为它们具有特定的结构,所以我们一般都是可以通过关系型数据库(MySQL,Oracle 等)的二维表(Table)的方式存储和搜索,也可以建立索引。

非结构化数据搜索:将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。将非结构化数据变得结构化的得到的就叫做倒排索引(关于倒排索引的更多介绍,参见ElasticSearch倒排索引)。ElasticSearch就是利用倒排索引对非结构化数据进行存储和高效检索。下面以传统数据库做类比分析。

在ElasticSearch中存储数据的行为就叫做索引(indexing)。在ElasticSearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,类比传统关系数据库:

ElasticSearch集群可以包含多个索引(indices)(数据库),每个索引可以包含多个类型(types)(表),每个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。

【索引】含义的区分

索引(名词):一个索引就像是传统关系数据库中的数据库,它是相关文档存储的地方,index的复数是indices或indexes。

索引(动词):“索引一个文档”表示把文档存储到索引(名词)里,以便它可以被检索或者查询。这很像SQL中的insert关键字,差别是,如果文档已经存在,新的文档将覆盖旧的文档。

倒排索引:传统数据库为特定列增加一个索引,例如B-Tree索引来加速检索。ElasticSearch和Lucene使用一种叫做倒排索引的数据结构来达到相同的目的。

由于ElasticSearch中的document使用JSON格式来存储的,因而默认情况下,文档中的所有字段都会被索引(拥有一个倒排索引),只有这样它们才是可以被索引的。这里的所有字段是指:json中的key(详见ElasticSearch倒排索引中的示例)。

关于type的理解

type是一个index中用来区分相似数据的,但是可能有不同的fields,而且有不同的属性来控制索引建立、分词器。field的value值在底层的lucene中建立索引的时候,全部是opaque bytes类型,不区分类型的。lucene是没有type的概念的,在document中,实际上将type作为一个document的field来存储,即_type,es通过_type来进行type的过滤和筛选。一个index中的多个type,实际上是放在一起存储的,因此一个index下,不能有多个type重名但是类型或其他设置不同,因为那样是无法处理的。

在es内部,会把所有field合并,对一个type中没有的field就用空值替代。所以在一个index下不同type的同名field的类型必须一致,否则就会冲突。最佳实践,将类似结构的type放在一个index下,这些type应该有多个field是相同的。因为如果将两个type的field完全不同的类型放在同一个index下,那么就每条数据都至少有一半的field在底层的lucene中是空值,会有严重的性能问题。

关于es为什么要移除type

1、index、type的初衷

之前es将index、type类比于关系数据库中的database、table,这么考虑的目的是“方便管理数据之间的关系”。

2、为什么现在要移除type

2.1 在关系类型数据库中table是独立的(独立存储),但es中同一个index中不同type是存储在同一个索引中的(lucene的索引文件),因此不同type中相同名字的字段的定义(mapping)必须一致。

2.2 不同类型(type)的“记录”存储在同一个index中,会影响lucene的压缩性能。因为在es内部,会把同一个index下不同type中的所有field合并,对于一个type中没有的field就用空值代替。因此,如果两个type的field完全不同,却放在一个index下,那么每条数据至少有一半的field在底层的lucene中是空值,会有严重的性能问题。

3、替换策略

3.1 一个index只存储一种类型(type)的“记录”

这种方案的优点:

a)lucene索引中数据比较整齐(相对于稀疏),利于lucene进行压缩。

b)文本相关性打分更加精确(tf、idf,考虑idf中命中文档总数)

3.2 用一个字段来存储type

如果有很多规模比较小的数据表需要建立索引,可以考虑放到同一个index中,每条记录添加一个type字段进行区分。

这种方案的优点:

a)es集群对分片数量有限制,这种方案可以减少index的数量。

这种方案本质上还是3.1方案,因为索引下还是只有一个type。

4、迁移方案

之前一个index上有多个type,如何迁移到3.1、3.2方案?

4.1 先针对实际情况创建新的index,[3.1方案]有多少个type就需要创建多少个新的index,[3.2方案]只需要创建一个新的index。

4.2 调用_reindex将之前index上的数据同步到新的索引上。

关于mapping

es的mapping类似于关系型数据库的数据表定义(ddl),示例如下:

1、创建新的索引(index)

代码语言:javascript复制
PUT /indexTest

返回结果:

代码语言:javascript复制
{
    "acknowledged":true,
    "shards_acknowledged":true,
    "index":"indexTest"
}

2、创建mapping

2.1 首先查看刚刚创建的索引的mapping是什么样子:

代码语言:javascript复制
GET /indexTest/_mapping

返回:

代码语言:javascript复制
{
    "indexTest":{
        "mapping":{}
    }
}

可见新建的索引中,mapping是一个空集。

2.2 创建mapping:

代码语言:javascript复制
POST /indexTest/product/_mapping?pretty
{
    "product":{
        "properties":{
            "title":{
                "type":"text",
                "store":"true"
            },
            "description":{
                "type":"text",
                "index":"false"
            },
            "price":{
                "type":"double"
            },
            "onSale":{
                "type":"boolean"
            },
            "type":{
                "type":"integer"
            },
            "createDate":{
                "type":"date"
            }
        }
    }
}

再次执行mapping查询指令得到:

代码语言:javascript复制
{
    "indexTest":{
        "mapping":{
            "product":{
                "properties":{
                    "title":{
                        "type":"text",
                        "store":"true"
                    },
                    "description":{
                        "type":"text",
                        "index":"false"
                    },
                    "price":{
                        "type":"double"
                    },
                    "onSale":{
                        "type":"boolean"
                    },
                    "type":{
                        "type":"integer"
                    },
                    "createDate":{
                        "type":"date"
                    }
                }
            }
        }
    }
}

3、插入数据:

代码语言:javascript复制
POST /indexTest/product
{
  "title": "test title 001",
  "description": "this is a random desc ",
  "price": 22.6,
  "onSale": "true",
  "type": 2,
  "createDate": "2018-01-12"

}

由此可见,mapping就是定义了index中的数据结构,类似于Mysql的DDL定义表结构。

参考文档:

1、《elasticsearch权威指南》

2、https://www.cnblogs.com/liuqianli/p/8475477.html es中的type数据类型

3、https://www.cnblogs.com/huangfox/p/9460361.html es为什么要移除type

4、https://blog.csdn.net/qq_15958689/article/details/79524291 ES(ElasticSearch) 索引创建

5、https://maimai.cn/article/detail?fid=1302443404&efid=CMeD__mXKvERfvRz34KMaA&from=singlemessage 看完这篇还不会Elasticsearch,我跪搓衣板

6、https://blog.csdn.net/Saintyyu/article/details/103076723 ElasticSearch倒排索引

7、https://blog.csdn.net/m0_38052384/article/details/103701051 Elasticsearch: 在主分片和复制分片上执行写、检索、局部更新的必要步骤

8、https://www.cnblogs.com/xjh713/p/10630887.html elasticsearch读写原理

0 人点赞