https://blog.csdn.net/ZYC88888/article/details/83027458

映射是定义一个文档以及其所包含的字段如何被存储和索引的方法。

1 mapping关系

image.png

2 ES 自动建立的mapping(Dynamic Mapping)

ES与关系型数据库不同之处在于,其不需要先定义表结构,而可以根据写入文档的内容,来推断字段和数据类型,创建索引结构,这就是dynamic mapping

按dynamic值,可分为下面三种模式

  • 动态模式(dynamic:true),根据输入文档的内容,自动推断字段和类型,创建mapping
  • 非动态模式(dynamic:false),无法根据输入文档的内容,自动创建mapping,需要手动创建mapping
  • 严格模式(dynamic:strict),同非动态模式,区别在于,非动态模式,输入的文档中如果有字段不在mapping中,依然可以存储和读取,但是该字段不在mapping中,因此也无法根据该字段进行检索;但严格模式,无法存储,会直接报错,严格模式实际上就类似于关系型数据库中的表了。

image.png

3 手动建立mapping

1、如何建立索引

analyzed
not_analyzed
no

2、修改mapping

1 只能创建index时手动建立mapping,或者新增field mapping
2 但是不能update field mapping

image.png

PUT /website
{
“mappings”: {
“article”: {
“properties”: {
“author_id”: {
“type”: “long”
},
“title”: {
“type”: “text”,
“analyzer”: “english”
},
“content”: {
“type”: “text”
},
“post_date”: {
“type”: “date”
},
“publisher_id”: {
“type”: “text”,
“index”: “not_analyzed”
}
}
}
}
}

PUT /website
{
“mappings”: {
“article”: {
“properties”: {
“author_id”: {
“type”: “text”
}
}
}
}
}

{
“error”: {
“root_cause”: [
{
“type”: “index_already_exists_exception”,
“reason”: “index [website/co1dgJ-uTYGBEEOOL8GsQQ] already exists”,
“index_uuid”: “co1dgJ-uTYGBEEOOL8GsQQ”,
“index”: “website”
}
],
“type”: “index_already_exists_exception”,
“reason”: “index [website/co1dgJ-uTYGBEEOOL8GsQQ] already exists”,
“index_uuid”: “co1dgJ-uTYGBEEOOL8GsQQ”,
“index”: “website”
},
“status”: 400
}

PUT /website/_mapping/article
{
“properties” : {
“new_field” : {
“type” : “string”,
“index”: “not_analyzed”
}
}
}

3、测试mapping

GET /website/_analyze
{
“field”: “content”,
“text”: “my-dogs”
}

GET website/_analyze
{
“field”: “new_field”,
“text”: “my dogs”
}

{
“error”: {
“root_cause”: [
{
“type”: “remote_transport_exception”,
“reason”: “[4onsTYV][127.0.0.1:9300][indices:admin/analyze[s]]”
}
],
“type”: “illegal_argument_exception”,
“reason”: “Can’t process field [new_field], Analysis requests are only supported on tokenized fields”
},
“status”: 400
}

4 source和store

https://blog.csdn.net/pony_maggie/article/details/113617710
1 ElasticSearch是以json格式存储原始文件数据的,_source字段表明是否存储这个原始文件数据
2 如果一个字段的mapping中含有store属性为true,那么有一个单独的存储空间为这个字段做存储,而且这个存储是独立于_source的存储的。且分词操作。
3 单独的存储空间不是指分词之后存储倒排索引所在的空间,因为我们把某个字段field映射为{“type”: “text”, “store”: true},字段值为”江西省”。通过term查找”江西省”不能匹配,term查找”江”, “西”, “省”确能匹配

4.1 _source

用途:

  • 重做索引
  • 修改mapping和分析器
  • 高亮提醒
  • 便于调试

    保留还是不保留

  • 取决于什么类型的数据,日志类型的索引基本不用保存

  • 为了避免过多占用磁盘空间,可以开启文件压缩

好处

(1)查询的时候,直接可以拿到完整的document,不需要先拿document id,再发送一次请求拿document
有时候我们并不需要这个source字段,只是希望拿到查询的结果,在一些业务场景下我们往往会用数据库的主键作为文档id。然后用这个id再进一步去其它的存储介质拿数据。因为source字段默认是打开的,如果你不了解这个机制,就白白浪费了ES的存储空间

(2)partial update基于_source实现
(3)reindex时,直接基于_source实现,不需要从数据库(或者其他外部存储)查询数据再修改
(4)可以基于_source定制返回field
(5)debug query更容易,因为可以直接看到_source

如果不需要上述好处,默认开启 可以禁用_source

PUT /my_index/_mapping/my_type2
{
“_source”: {“enabled”: false}
}
只存储address和baseAddress字段

  1. {
  2. "yourtype":{
  3. "_source":{
  4. "includes":["address", "baseAddress"]
  5. },
  6. "properties": {
  7. ...
  8. }
  9. }
  10. }

4.2 设置store

  1. {
  2. "household-address": {
  3. "properties": {
  4. "address": {
  5. "type": "keyword",
  6. "store": true
  7. },
  8. "baseAddress": {
  9. "type": "keyword",
  10. "store": false
  11. }
  12. }
  13. }
  14. }

查询过滤store字段

  1. {
  2. "stored_fields": [ "address", "baseAddress" ]
  3. }

4.3 两者优点和缺点

1 使用store存储字段field会占用磁盘空间。如果需要从文档中提取(即在脚本中和聚合)它会帮助减少计算。在聚合时具有store属性的字段会比不具有这个属性的字段快
2 从每一个stored field中获取值都需要一次磁盘io,如果想获取多个field的值就需要多次磁盘io。但从_source中获取多个field的值则只需要一次磁盘io因为_source只是一个字段而已,而且_source是被压缩过的。所以在大多数情况下,从_source中获取是快速而高效的。
3 从_source中获取值是快速而且高效的。但如果你的文档长度很长,存储 _source或者从_source中获取field的代价很大,你可以显式的将某些field的store属性设置为yes。

5 all和copy_to属性

1 在6.0+中_all字段默认被禁用,同时在创建index的时候不能enable;建议使用copy_to 实现用户自定义的_all 功能。
2 copy_to可以把该字段的值拷贝到一个新的字段当中去。
3 如果要复制到的目标字段(下例中的address字段)类型是text,则不管源字段(下例中的baseAddress字段)是什么类型,建立倒排索引都会进行分词。
4 如果要复制到的目标字段(下例中的address字段)类型是keyword,则不管源字段(下例中的baseAddress字段)是什么类型,建立倒排索引都不会分词且分别对各个字段原始值建立索引
如下例:“address”: “广东省”,“baseAddress”: “抚州市”,“detailAddress”: “广昌县”。则对address建立了三个索引[“广东省”, “抚州市”, “广昌县”],而不会建立”广东省抚州市广昌县”索引。

1 all 将所有field打包在一起,作为一个_all field,建立索引。没指定任何field进行搜索时,就是使用_all field在搜索

PUT /my_index/_mapping/my_type3
{
“_all”: {“enabled”: false}
}
2 设置copy_to
PUT /network-loan-apply-household-address/_mapping/household-address

  1. {
  2. "household-address": {
  3. "properties": {
  4. "address": {
  5. "type": "keyword",
  6. "ignore_above": 256,
  7. "index" : true,
  8. "store": false
  9. },
  10. "baseAddress": {
  11. "type": "text",
  12. "index" : true,
  13. "store": false,
  14. "copy_to": "address"
  15. },
  16. "detailAddress": {
  17. "type": "text",
  18. "index" : true,
  19. "store": false,
  20. "copy_to": "address"
  21. }
  22. }
  23. }
  24. }

6. index索引属性

控制某个字段是否生成倒排索引;
1 Elasticsearch 5之前,index属性的取值有三个:analyzed-字段被索引,会做分词,可搜索。
2 not_analyzed-字段值不分词,会被原样写入索引,可搜索。no-字段不写入索引,也就不能搜索
3 在Elasticsearch 5之后index属性的取值有两个:true-字段被索引,可搜索;false-字段不被索引,不可被搜索。至于会不会做分词则通过字符串是text还是keyword来区分

6.1 text和keyword

在es 2.版本里面是没有这两个字段只有string字段;5.之后取消了string,引入text,keyword字段
1 text做倒排索引时会分词,支持全文检索,支持模糊、精确查询,不支持聚合,排序操作;
2 text类型的最大支持的字符长度无限制(对于text字段不支持ignore_above),适合大字段存储;
3 keyword做倒排索引时不进行分词,支持模糊、精确匹配,支持聚合、排序操作。
4 keyword类型的最大支持的长度为——32766个UTF-8类型的字符,可以通过设置ignore_above指定自持字符长度,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。
5 只有keyword类型支持ignore_above,超过这个长度的字段不会建立倒排索引,所以也不能被搜索

PUT /network-loan-apply-household-address/_mapping/household-address


8 term&match

  1. term&match
    term: 精确查询,对查询的值不分词,直接进倒排索引去匹配。
    match; 模糊查询,对查询的值分词,对分词的结果一一进入倒排索引去匹配
    2. text&keyword
    text: 在写入时,对写入的值进行分词,然后一一插入到倒排索引。
    keyword: 在写入时,将整个值插入到倒排索引中,不进行分词。