Loading... # Elasticsearch(四) ## Mapping Mapping就是ES数据字段field的type元数据,ES在创建索引的时候,dynamic mapping会自动为不同的数据指定相应mapping。mapping中包含了字段的类型、搜索方式(exact value或者full text)、分词器等。 ### 查看mapping ``` GET product/_mappings ``` ### Dynamic mapping - 字符串: text/keyword - 数字: long - 浮点数: double - true/false: boolean - yyyy-MM-dd: date 为什么数字类型是long而不是integer?因为ES的mapping_type是由JSON分析器检测数据类型,而JSON没有隐式类型转换,所以dynamic mapping会选择一个比较宽的数据类型。但实际使用中发现浮点数会自动创建为float类型,不知道是否是ES的BUG。 ### 搜索方式 - exact value: 精确匹配,在倒排索引过程中,分词器会将field作为一个整体创建到索引中。 - full text: 分词、近义词同义词、混淆词、大小写、词性、过滤、时态转换等(normalization)。 ### ES数据类型 #### 核心类型 - 数字类型 - long,integer,short,byte,double,float,half_float,scaled_float - 在满足需求的情况下,尽可能选择范围小的数据类型。 - 字符串 - keyword: 适用于索引结构化的字段,可以用于过滤、排序、聚合。keyword类型的字段只能通过精确值(exact value)搜索到。id应该用keyword。 - text: 当一个字段是要被全文搜索的,比如Email内容、产品描述,这些字段应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。默认不会为text创建索引,因为字段数据会占用大量堆空间,尤其是在加载高基数text字段时。字段数据一旦加载到堆中,就在该字段的生命周期内保持在那里。同样,加载字段数据是一个昂贵的过程,可能导致用户遇到延迟问题,这就是默认情况下禁用字段数据的原因。 - 有时,在同一字段中同时具有全文本(text)和关键字(keyword)版本会很有用,一个用于全文本搜索,另一个用于聚合和排序。 - date(时间类型): 属于exact value,不会被分词 - 布尔类型: boolean - binary(二进制): binary - range(区间类型): integer_range、float_range、long_range、double_range、date_range #### 复杂类型 - Object: 用于单个JSON对象 - Nested: 用于JSON对象数组 #### 地理位置 - Geo-point: 纬度/经度积分 - Geo-shape: 用于多边形等复杂形状 #### 特有类型 - IP地址: ip 用于IPv4和IPv6地址 - Completion: 提供自动完成建议 - Tocken_count: 计算字符串中令牌的数量 - Murmur3: 在索引时计算值的哈希并将其存储在索引中 - Annotated-text: 索引包含特殊标记的文本(通常用于标识命名实体) - Percolator: 接受来自query-dsl的查询 - Join: 为同一索引内的文档定义父/子关系 - Rank features: 记录数字功能以提高查询时的点击率 - Dense vector: 记录浮点值的密集向量 - Sparse vector: 记录浮点值的稀疏向量 - Search-as-you-type: 针对查询优化的文本字段,以实现按需输入的完成 - Alias: 为现有字段定义别名 - Flattened: 允许将整个JSON对象索引为单个字段 - Shape: shape对于任意笛卡尔几何 - Histogram: histogram用于百分位数聚合的预聚合数值 - Constant keyword: keyword当所有文档都具有相同值时的情况的专业化 #### Array(数组) 在Elasticsearch中,数组不需要专用的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值都必须具有相同的数据类型。 ### 手工创建mapping ``` PUT /product { "mappings": { "properties": { "date": { "type": "text" }, "desc": { "type": "text", "analyzer": "english" }, "name": { "type": "text", "index": "false", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "price": { "type": "long" }, "tags": { "type": "text", "index": "true" }, "parts": { "type": "object" }, "partlist": { "type": "nested" } } } } ``` 插入数据 ``` PUT /product3/_doc/1 { "name": "xiaomi phone", "desc": "shouji zhong de zhandouji", "count": 123456, "price": 3999, "date": "2020-05-20", "isdel": false, "tags": [ "xingjiabi", "fashao", "buka" ], "parts": { "name": "adapter", "desc": "5V 2A" }, "partlist": [ { "name": "adapter", "desc": "5V 2A" }, { "name": "USB-C", "desc": "5V 2A 1.5m" }, { "name": "erji", "desc": "boom" } ] } ``` ### Mapping参数 - index: 是否对当前字段创建索引,默认true,如果不创建索引,将无法通过该字段检索数据,但通过其他字段检索时,该字段仍会在结果中返回。 - analyzer: 指定分析器(character filter、tokenizer、Token filters)。 - boost: 对当前字段相关度的评分权重,默认1。 - coerce: 是否允许强制类型转换,默认true,用于数字类型中,当为true时,插入字符串会隐式转换成数字类型,如果为false会抛出异常。 - copy_to: 允许通过其他字段来索引该字段的数据。 ``` PUT copy_to { "mappings": { "properties": { "field1": { "type": "text", "copy_to": "field_all" }, "field2": { "type": "text", "copy_to": "field_all" }, "field_all": { "type": "text" } } } } ``` - 允许通过field_all字段来检索field1与field2的数据,即使field_all字段没有值。 - doc_values: 为了提升排序和聚合效率,默认true,如果确定不需要对字段进行排序或聚合,也不需要通过脚本访问字段值,则可以禁用doc_values以节省磁盘空间(不支持text和annotated_text)。 - dynamic: 控制是否可以动态添加新字段 - true: 新检测到的字段将添加到映射中。(默认) - false: 新检测到的字段将被忽略。这些字段将不会被索引,因此将无法搜索,但仍会出现在_source返回得到匹配项中。这些字段不会添加到映射中,必须显式添加新字段。 - strict: 如果检测到新字段,则会引发异常并拒绝文档。必须将新字段显式添加到映射中。 ``` PUT dynamic { "mappings": { "dynamic": "strict", "properties": { "user": { "properties": { "date": { "type": "text" }, "desc": { "type": "text", "analyzer": "english" }, "name": { "type": "text", "index": "false" }, "price": { "type": "long" } } } } } } ``` - eager_global_ordinals: 用于聚合字段上,优化聚合性能。 - Frozen indices(冻结索引): 有些索引使用频率很高,会被保存在内存中,有些使用频率特别低,宁愿在使用的时候重新创建,在使用完毕后丢弃数据,Frozen indices的数据命中频率小,不适用于高搜索负载,数据不会被保存在内存中,堆空间占用比普通索引少的多,Frozen indices是只读的,请求可能是秒级或者分钟级。eager_global_ordinals不适用于Frozen indices。 - enable: 是否创建倒排索引,可以对字段操作,也可以对索引操作,如果不创建索引,仍然可以检索并在_source返回结果中展示,谨慎使用,该状态无法修改。 ``` PUT my_index { "mappings": { "enabled": false, "properties": { "session_data": { "type": "object" } } } } ``` ``` PUT my_index { "mappings": { "properties": { "session_data": { "type": "object", "enabled": false } } } } ``` - fielddata: 查询时内存数据结构,在首次用当前字段聚合、排序或者在脚本中使用时,需要字段为fielddata数据结构,并且创建正排索引保存到堆中。 - fields: 给field创建多字段,用于不同目的(全文检索或者聚合分析排序)。 - format: 格式化 ``` "date": { "type": "date", "format": "yyyy-MM-dd" } ``` - ignore_above: 超过长度将被忽略 - ignore_malformed: 忽略类型错误 ``` PUT my_index { "mappings": { "properties": { "number_one": { "type": "integer", "ignore_malformed": true }, "number_two": { "type": "integer" } } } } ``` ``` PUT my_index/_doc/1 { "text": "Some text value", "number_one": "foo" # number_one设置了ignore_malformed 虽然有异常,但是不会抛出 } ``` ``` PUT my_index/_doc/1 { "text": "Some text value", "number_two": "foo" # number_two没有设置了ignore_malformed 数据格式不对 } ``` - index_options: 控制将哪些信息添加到反向索引中以进行搜索和突出显示。仅用于text字段。 - index_phrases: 提升exact_value查询速度,但是消耗更多磁盘空间。 - index_prefixes: 前缀搜索 - min_chars: 前缀最小长度,大于0,默认2 - max_chars: 前缀最大长度,小于20,默认5 ``` "index_prefixes": { "min_chars" : 1, "max_chars" : 10 } ``` - meta: 附加元数据 - normalizer: keyword字段的normalizer属性类似于分析器,只是它保证分析链生成单个token。 - norms: 是否禁用评分,在filter和聚合字段上应该禁用。 - null_value: 为null值设置默认值。 - position_increment_gap: 在为文本值数组建立索引时,Elasticsearch在一个值的最后一项和下一个值的第一项之间插入一个假的“空白”,以确保词组查询与来自不同数组元素的两项不匹配。默认为100。 - properties: 除了mapping还可用于object的属性设置。 - search_analyzer: 设置单独的查询时分词器。 - similarity: 为字段设置相关度算法,支持BM25、claassic(TF-IDF)。 - store: 设置字段是否仅查询。 - term_voctor: 对分词信息进行计算、统计。 ### 聚合查询 - bucket: 一个数据分组 - metirc: 对一个数据分组执行的统计 #### 聚合语法 ``` aggs:{ code... } ``` #### 简单聚合 统计价格大于1999数据的tag类型以及每一种类的数量 ``` GET product/_search { "query": { "constant_score": { "filter": { "range": { "price": { "gt": 1999 } } } } }, "aggs": { "tag_agg_group": { "terms": { "field": "tags.keyword", "size": 10 } } }, "size": 0 } ``` #### avg平均值 统计价格大于1999的每个tag产品的平均价格 ``` GET product/_search { "query": { "constant_score": { "filter": { "range": { "price": { "gt": 1999 } } } } }, "aggs": { "avg": { "terms": { "field": "tags.keyword", "order": { "avg_price": "desc" } }, "aggs": { "avg_price": { "avg": { "field": "price" } } } } }, "size": 0 } ``` #### 分组聚合 按照千元机: 1000一下,中端机: 2000-3000,高端机: 3000以上分组聚合,分别计算数量,并计算每组平均价格。 ``` GET product/_search { "aggs": { "tag_agg_group": { "range": { "field": "price", "ranges": [ { "from": 100, "to": 1000 }, { "from": 1000, "to": 2000 }, { "from": 3000 } ] }, "aggs": { "price_agg": { "avg": { "field": "price" } } } } }, "size": 0 } ``` 如果出现TooManyBucketsException异常,这是6.x以后版本的特性,目的是限制大批量聚合操作,规避性能风险。需要设置: ``` PUT _cluster/settings { "persistent": { "search.max_buckets":1000000 } } ``` Last modification:July 28th, 2020 at 11:03 am © 允许规范转载