Elasticsearch系列---定制mapping

概要

本篇接着前一篇内容,继续介绍mapping信息,重点倾向于自定义mapping、自定义对象以及数组集合类的底层结构。

自定义mapping

上一篇文章介绍的都是Elasticsearch的自动mapping,我们在创建索引时,可以先指定好mapping的信息,还是以music索引为例:

PUT /music
{
  "mappings": {
    "children": {
      "properties": {
        "content": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "language": {
          "type": "keyword"
        },
        "length": {
          "type": "long"
        },
        "likes": {
          "type": "long"
        },
        "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

共包含name,content,language,length,likes 5个field,这里我们把language field的type指定为keyword,这个field无需分词,精确匹配即可。

修改mapping

我们可以在创建索引时指定mapping信息,也可以为索引增加新的field时指定mapping信息,但是已经存在的field,我们不能修改其mapping,否则会报错,例如:
我们为music索引增加一个author field,并指定其type为text,analyzer、search_analyzer均为english

PUT /music/_mapping/children
{
  "properties" : {
    "author" : {
      "type" : "text",
      "index": true,
      "analyzer": "english",
      "search_analyzer": "english"
    }
  }
}

如果尝试修改一下已经存在的field,如name字段,则会提示报错:
请求:

PUT /music/_mapping/children
{
  "properties" : {
    "name" : {
      "type" : "text",
      "index": true,
      "analyzer": "english",
      "search_analyzer": "english"
    }
  }
}

报错信息:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "Mapper for [name] conflicts with existing mapping in other types:\n[mapper [name] has different [analyzer]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "Mapper for [name] conflicts with existing mapping in other types:\n[mapper [name] has different [analyzer]]"
  },
  "status": 400
}

复杂数据类型底层结构

前面提及的mapping信息,都是针对基础数据类型的,我们知道Elasticsearch是面向对象的分布式存储文档系统,肯定会遇到各种各样的自定义对象、集合数组、嵌套对象等数据结构,ES是如何支持、处理这些复杂对象类型的呢?

  1. 数组、集合类

集合在JSON串中与数组等同,均可以认为是数组类型,在Elasticsearch中对数组没有特殊的映射需求,建立索引时与text是一样的,也是分词处理后得到多个词条,建立倒排索引。

有一点要注意的是数组内的元素,数据类型要一致,比如都是字符器,都是日期,或都是数值,不能混搭,自动mapping是以第1位元素来决定type的,如果混搭,数组内与第1位元素类型不一致的元素,索引时会报错。

  1. Null类型
    底层的Lucene不能存储null值,null类型的不会被索引:
"null_value":               null,
"empty_array":              [],
"array_with_null_value":    [ null ]
  1. 复杂对象
    复杂对象一般有一层或多层嵌套,即对象中的属性,类型也是对象,有时候还混搭着数组一类的,举个例子:
{
  "address": {
    "country": "CN",
    "province": "GD",
    "city": "SZ"
  },
  "name": "Herry",
  "age": 28,
  "birth_date": "1992-04-29"
}

人员信息除了姓名年龄外,还有地址信息address,而address属性本身也是个对象,里面包含了country、province、city三个属性,查看它的mapping信息,也是呈嵌套结构(内容有删除,只保留体现层级的属性):

{
  "person": {
    "mappings": {
      "info": {
        "properties": {
          "address": {
            "properties": {
              "city": {
                "type": "text"
              },
              "country": {
                "type": "text"
              },
              "province": {
                "type": "text"
              }
            }
          }
        }
      }
    }
  }
}

Elasticsearch在存储层级结构的数据对象时,会做一些扁平化处理,Luence文档是一组KV结构的列表,把上述的数据存储成这样:

{
  "address.country": "CN",
  "address.province": "GD",
  "address.city": "SZ",
  "name": "Herry",
  "age": 28,
  "birth_date": "1992-04-29"
}

所以最终想要根据address下的country作为条件进行查询,应该这么写:

GET /person/info/_search
{
  "query": {
    "match": {
      "address.country": "CN"
    }
  }
}
  1. 数组内的复杂对象
    数组内的元素如果是基础数据类型还好说,只要求数组内所有元素类型一致即可,如果里面的元素是一个对象,又是如何索引的呢?
    假如一个数组结构是这样的:
{
    "likes": [
        { "name": "Three Zhang", "datetime": "2019-12-01 08:58:12"},
        { "name": "Four Lee", "datetime": "2019-12-01 09:12:23"},
        { "name": "Five Wang", "datetime": "2019-12-01 09:15:58"}
    ]
}

经过扁平化处理(由列变成行),得到的数据将会是这样:

{
    "likes.name": ["Three Zhang","Four Lee","Five Wang"],
    "likes.datetime": ["2019-12-01 08:58:12","2019-12-01 09:12:23","2019-12-01 09:15:58"],
}

发现什么问题没?这样处理完了之后,原本对象之间的关联性就没有了,数组内只是一堆无序的元素,如果要查询"Three Zhang在2019-12-01 09:00:00之后有没有给我点过赞"这样的组合条件查询,是会出现一条查询记录的,这跟预期的结果不同,显然是错了。

留意一下这个问题,数组内的元素是对象类型时,需要声明为nested类型,才能得到预期的查询效果,nested类型在后续会有介绍。

小结

本篇主要对mapping的内容进行一些补充,并简单描述了各种复杂对象的底层存储结构,需要注意的是数组内的对象处理,需要声明为nested才能得到正确的结果。

专注Java高并发、分布式架构,更多技术干货分享与心得,请关注公众号:Java架构社区

原文地址:https://www.cnblogs.com/huangying2124/p/12105382.html

时间: 2024-08-29 20:56:30

Elasticsearch系列---定制mapping的相关文章

Elasticsearch系列---初识mapping

概要 本篇简单介绍一下field数据类型mapping的相关知识. mapping是什么? 前面几篇的实战案例,我们向Elasticsearch索引数据时,只是简单地把JSON文本放在请求体里,至于JSON里的field类型,存储到ES里是什么类型,中间是怎么做的映射,这个映射过程,就是mapping要解决的问题. mapping简单来说,就是解决JSON文本内容到field类型映射关系的定义.将时间域视为时间类型,数字视为数字类型,字符串识别为全文或精确值字符串,这个识别的过程,叫做mappi

第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲-elasticsearch(搜索引擎)的mapping映射管理 1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字段的类型以及相关属性elasticsearch会根据json源数据的基础类型猜测你想要的字段映射,将输入的数据转换成可搜索的索引项,mapping就是我们自己定义的字段数据类型,同时告诉elasticsearch如何索引数据以及是否可以被搜索 作用:会让索引建立的更加细致和完善 类型:静态映射和动态

elasticsearch中的mapping映射配置与查询典型案例

elasticsearch中的mapping映射配置示例比如要搭建个中文新闻信息的搜索引擎,新闻有"标题"."内容"."作者"."类型"."发布时间"这五个字段:我们要提供"标题和内容的检索"."排序"."高亮"."统计"."过滤"等一些基本功能.ES提供了smartcn的中文分词插件,测试的话建议使用IK分

Elasticsearch:Dynamic mapping

Elasticsearch最重要的功能之一是它试图摆脱你的方式,让你尽快开始探索你的数据. 要索引文档,您不必首先创建索引,定义映射类型和定义字段 - 您只需索引文档,那么index,type和field将自动生效.比如: PUT data/_doc/1 { "count": 5 } 上面的命令将自动帮我们生成一个叫做data的index,并同时生成一个叫做_doc的type及一个叫做count的field.count的数据类型是long.这个非常方便,我们不想传统的RDMS那样,先要

Elasticsearch系列---索引管理

概要 Elasticsearch让索引创建变得非常简单,只要索引一条新的数据,索引会自动创建出来,但随着数据量的增加,我们开始有了索引优化和搜索优化的需求之后,就会发现自动创建的索引在某些方面不能非常完美的适应我们的需求,我们开始考虑手动创建适合我们业务需求的索引. 索引的CRUD 为了更好地贴切我们的业务数据需求,我们开始更精细的管理我们的索引. 创建索引 创建索引的语法示例如下: PUT /music { "settings": { "number_of_shards&q

ElasticSearch Index API && Mapping

ElasticSearch  NEST Client 操作Index var indexName="twitter"; var deleteIndexResponse = client.DeleteIndex(indexName);                var createIndexResponse = client.CreateIndex(indexName);                var getIndexResponse = client.GetIndex(in

ElasticSearch 基础(4) - Mapping

一.Mapping概述 为了能够把日期字段处理成日期,把数字字段处理成数字,把字符串字段处理成Full-text或者精确的字符串值. ES需要知道每个字段里面都包含了什么类型.这些类型和字段的信息存储(包含)在映射(mapping)中. 索引中每个文档都有一个类型(type).每个类型都拥有自己的映射(mapping)或者模式定义(schema definition). 一个映射定义了字段类型,每个字段的数据类型,以及字段被Elasticsearch处理的方式.映射还用于设置关联到类型上的元数据

elasticsearch index 之 Mapping

Lucene索引的一个特点就filed,索引以field组合.这一特点为索引和搜索提供了很大的灵活性.elasticsearch则在Lucene的基础上更近一步,它可以是 no scheme.实现这一功能的秘密就Mapping.Mapping是对索引各个字段的一种预设,包括索引与分词方式,是否存储等,数据根据字段名在Mapping中找到对应的配置,建立索引.这里将对Mapping的实现结构简单分析,Mapping的放置.更新.应用会在后面的索引fenx中进行说明. 首先看一下Mapping的实现

elasticsearch中的mapping简介

Mapping Mapping is the process of defining how a document should be mapped to the Search Engine, including its searchable characteristics such as which fields are searchable and if/how they are tokenized. In Elasticsearch, an index may store document