文档章节

Elasticsearch 同一索引不同类型下同名字段的映射冲突实例

MrYx3en
 MrYx3en
发布于 2015/11/16 19:55
字数 1063
阅读 147
收藏 3
点赞 0
评论 0

    这个标题肯定绕晕很多人吧。具体说明一下场景就明白了:Nginx 和 Apache 的访问日志,因为都属于网站访问,所以写入到同一个索引的不同类型下,比方 logstash-accesslog-2015.04.03/nginx 和 logstash-accesslog-2015.04.03/apache。既然都是访问日志,肯定很多字段的内容含义是雷同的,比如 clientip, domain, urlpath 等等。其中 nginx 有一个变量叫 $request_time,apache 有一个变量叫 %T,乍看上去也是同义的,我就统一命名为 “requestTime” 了。这就是”同一索引(logstash-accesslog-YYYY.MM.DD)下不同类型(nginx,apache)的同名字段(requestTime)”。

但事实上,这里有个问题:nginx 中的以秒为单位,是把毫秒算作小数;apache 中的以秒为单位,是真的只记秒钟整数位!

所以,这两个类型生成的映射在这个字段上是不一致的。nginx 类型的 requestTime 是 double,apache 类型的 requestTime 是 long

不过平常看起来似乎也没什么影响,写入数据都照常,查看数据的时候默认显示的 JSON 也各自无异。直到我准备用一把 scripted field 的时候,发现计算 doc['requestTime'].value * 1000 得到的数都大的吓人!

因为类似计算之前在只有 nginx 日志入库的时候曾经正确运行过,所以只能是猜测 apache 日志对此造成了影响,但是即使我把请求修改成限定在 nginx 类型数据中进行,结果也没发生变化。

仔细阅读 scripting module 的文档,其中提到了 doc['fieldname'].value 和_source.fieldname 两种写法的区别:前者会利用内存中的数据,而后者强制读取磁盘上_source 存储的 JSON 内容,从中释放出相应字段内容。莫非是 requestTime 字段跟_source JSON 里存的数据确实不一样,而我们平常搜索查看的都是从 JSON 里释放出来的,所以才会如此?

为了验证我的猜测,做了一个请求测试:

# curl es.domain.com:9200/logstash-accesslog-2015.04.03/nginx/_search?q=_id:AUx-QvSBS-dhpiB8_1f1\&pretty -d '{     
        "fields": ["requestTime", "bodySent"],     
        "script_fields" : {         
            "test1" : {             
                "script" : "doc[\"requestTime\"].value"         
            },         
            "test3" : {             
                "script" : "_source.bodySent / _source.requestTime"         
            },         
            "test2" : {             
                "script" : "doc[\"requestTime\"].value * 1000"         
            }     
         } 
     }'

得到的结果如下:

{   
    "took" : 43,   
    "timed_out" : false,   
    "_shards" : {     
    "total" : 56,     
    "successful" : 56,     
    "failed" : 0   
    },   
    "hits" : {     
        "total" : 1,     
        "max_score" : 1.0,     
        "hits" : [ {       
        "_index" : "logstash-accesslog-2015.04.03",       
        "_type" : "nginx",       
        "_id" : "AUx-QvSBS-dhpiB8_1f1",       
        "_score" : 1.0,       
        "fields" : {         
            "test1" : [ 4603039107142836552 ],         
            "test2" : [ -8646911284551352000 ],         
            "requestTime" : [ 0.54 ],         
            "test3" : [ 2444.4444444444443 ],         
            "bodySent" : [ 1320 ]       
            }     
        } ]   
    } 
}

果然!直接读取的字段,以及采用 _source.fieldname 方式读取的内容,都是正确的;而采用doc['fieldname'].value 获取的内存数据,就不对。(0.54 存成 long 型会变成 4603039107142836552。这个 460 还正好能跟 540 凑成 1000,应该是某种特定存法,不过这里我就没深究了)

再作下一步验证。我们知道,ES 数据的映射是根据第一条数据的类型确定的,之后的数据如何类型跟已经成型的映射不统一,那么写入会失败。现在这个 nginx 和 apache 两个类型在 requestTime 字段上的映射是不一样的,但是内存里却并没有按照映射来处理。那么,我往一个类型下写入另一个类型映射要求的数据,会报错还是会通过呢?

# curl -XPOST es.domain.com:9200/test/t1/1 -d '{"key":1}' 
{"_index":"test","_type":"t1","_id":"1","_version":1,"created":true} 
# curl -XPOST es.domain.com:9200/test/t2/1 -d '{"key":2.2}' 
{"_index":"test","_type":"t2","_id":"1","_version":1,"created":true} 
# curl -XPOST es.domain.com:9200/test/t1/2 -d '{"key":2.2}' 
{"_index":"test","_type":"t1","_id":"2","_version":1,"created":true} 
# curl -XPOST es.domain.com:9200/test/t2/2 -d '{"key":1}' 
{"_index":"test","_type":"t2","_id":"2","_version":1,"created":true} 
# curl -XPOST es.domain.com:9200/test/t1/3 -d '{"key":"1"}' 
{"_index":"test","_type":"t1","_id":"3","_version":1,"created":true} 
# curl -XPOST es.domain.com:9200/test/t2/3 -d '{"key":"1"}' 
{"_index":"test","_type":"t2","_id":"3","_version":1,"created":true} 
# curl -XPOST es.domain.com:9200/test/t2/4 -d '{"key":"abc"}' 
{"error":"RemoteTransportException[[10.10.10.10][inet[/10.10.10.10:9300]][indices:data/write/index]]; nested: MapperParsingException[failed to parse [key]]; nested: NumberFormatException[For input string: \"abc\"]; ","status":400} 
# curl -XGET es.domain.com:9200/test/_mapping 
{"test":{"mappings":{"t1":{"properties":{"key":{"type":"long"}}},"t2":{"properties":{"key":{"type":"double"}}}}}}

结果出来了,在映射相互冲突以后,实际数据只要是 numeric detect 能通过的,就都通过了!

BTW: kibana 4 中,已经会对这种情况以黄色感叹号图标做出提示;而根据官方消息,ES 未来会在 2.0 版正式杜绝这种可能。


本文转载自:http://chenlinux.com/2015/04/03/types-mapping-conflict-in-one-index/

共有 人打赏支持
MrYx3en
粉丝 9
博文 88
码字总数 30598
作品 0
宝鸡
系统管理员
Elasticsearch内核解析 - 数据模型篇

Elasticsearch是一个实时的分布式搜索和分析引擎,它可以帮助我们用很快的速度去处理大规模数据,可以用于全文检索、结构化检索、推荐、分析以及统计聚合等多种场景。 Elasticsearch是一个建...

少强 ⋅ 04/16 ⋅ 0

在 Python 中使用 Elasticsearch

在这篇文章中,我将讨论 Elasticsearch 以及如何将其整合到不同的 Python 应用程序中。 什么是 ElasticSearch? ElasticSearch(ES)是一个建立在 Apache Lucene 之上的高度可用的分布式开源...

xjtuhit ⋅ 06/13 ⋅ 0

Elasticsearch 5.5.1的安装和入门教程(转)

说明:转自老阮的文章,业界最简单的入门教程。一切的安装的运行建议不要用root权限,最好是当前用户下的权限。 作者: 阮一峰 日期: 2017年8月17日 全文搜索属于最常见的需求,开源的 Elas...

easonjim ⋅ 01/21 ⋅ 0

使用阿里云Elasticsearch搭建ELK日志系统

1. 搭建专用网络 1.1 登录专有网络管理控制台 阿里云Elasticsearch是搭建在专有网络上的,所以我们先开通阿里云专有网络, 点击开通 . 1.2 创建专有网络 点击创建专有网络 在专有网络名称和交...

pcdog ⋅ 05/21 ⋅ 0

CTO详细讲解海量日志处理ELK

ELK实时日志分析平台之Elasticsearch简介 Elasticsearch是一个高度灵活的开源全文检索和分析引擎。它能够迅速(几乎是实时地)地存储、查找和分析大规模数据。通常被用在有复杂的搜索要求的系...

Java架构分享 ⋅ 05/23 ⋅ 0

Elasticsearch是如何做到快速索引的

最近在参与一个基于Elasticsearch作为底层数据框架提供大数据量(亿级)的实时统计查询的方案设计工作,花了些时间学习Elasticsearch的基础理论知识,整理了一下,希望能对Elasticsearch感兴趣...

浮躁的码农 ⋅ 05/30 ⋅ 0

Elasticsearch内核解析 - 写入流程

目前的Elasticsearch有两个明显的身份,一个是分布式搜索系统,另一个是分布式NoSQL数据库,对于这两种不同的身份,读写语义基本类似,但也有一点差异。 写操作 实时性: 搜索系统的Index一般...

少强 ⋅ 04/16 ⋅ 0

Spark中hive的使用(hive操作es示例)

配置hive-site.xml <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value> <description>JDBC connect ......

守望者之父 ⋅ 06/15 ⋅ 0

Java搜索引擎选择: Elasticsearch与Solr(转)

Elasticsearch简介 Elasticsearch是一个实时的分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据。 它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组...

easonjim ⋅ 2017/11/13 ⋅ 0

全文搜索引擎 Elasticsearch 教程

文章目录 一、安装 二、基本概念 三、新建和删除 Index 四、中文分词设置 五、数据操作 六、数据查询 七、参考链接 全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是...

John ⋅ 06/19 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 17分钟前 ⋅ 0

VS2015配置并运行汇编(一步一步照图做)【vs2017的链接在最后】

前言 我是上学期学的汇编,因为有vs又不想用课上教的麻烦的dosbox以及masm32,但是一直没找到高亮插件和能调试的(难在运行不了而找不到答案上,出现的错误在最后放出,还请先达们不吝指点)...

simpower ⋅ 26分钟前 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 29分钟前 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 36分钟前 ⋅ 0

你真的明白RPC 吗?一起来探究 RPC 的实质

你真的明白RPC 吗?一起来探究 RPC 的实质 不论你是科班出身还是半路转行,这么优秀的你一定上过小学语文,那么对扩句和缩句你一定不陌生。缩句就是去除各种修饰提炼出一句话的核心,而不失基...

AI9o後 ⋅ 38分钟前 ⋅ 0

z-index设置失效?

今天碰到了一个问题,就是在给li设置提示框的时候,有用到遮罩效果,本来想把对应的出现在最顶层,可是不管将li设置的z-index值设为多大,li都没有出现在遮罩层之上。 我在网上查了z-index设...

IrisHunag ⋅ 45分钟前 ⋅ 0

CyclicBarrier、CountDownLatch以及Semaphore使用及其原理分析

CyclicBarrier、CountDownLatch以及Semaphore是Java并发包中几个常用的并发组件,这几个组件特点是功能相识很容易混淆。首先我们分别介绍这几个组件的功能然后再通过实例分析和源码分析其中设...

申文波 ⋅ 49分钟前 ⋅ 0

Java对象的序列化与反序列化

Java对象的序列化与反序列化

Cobbage ⋅ 今天 ⋅ 0

Sqoop

1.Sqoop: 《=》 SQL to Hadoop 背景 1)场景:数据在RDBMS中,我们如何使用Hive或者Hadoop来进行数据分析呢? 1) RDBMS ==> Hadoop(广义) 2) Hadoop ==> RDBMS 2)原来可以通过MapReduce I...

GordonNemo ⋅ 今天 ⋅ 0

全量构建和增量构建的区别

1.全量构建每次更新时都需要更新整个数据集,增量构建只对需要更新的时间范围进行更新,所以计算量会较小。 2.全量构建查询时不需要合并不同Segment,增量构建查询时需要合并不同Segment的结...

无精疯 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部