云服务器内容精选
-
文件格式的公共参数 启动作业标识文件 这个主要用于自动化场景中, CDM 配置了定时任务,周期去读取源端文件,但此时源端的文件正在生成中,CDM此时读取会造成重复写入或者是读取失败。所以,可以在源端作业参数中指定启动作业标识文件为“ok.txt”,在源端生成文件成功后,再在文件目录下生成“ok.txt”,这样CDM就能读取到完整的文件。 另外,可以设置超时时间,在超时时间内,CDM会周期去查询标识文件是否存在,超时后标识文件还不存在的话,则作业任务失败。 启动作业标识文件本身不会被迁移。 作业成功标识文件 文件系统为目的端的时候,当任务成功时,在目的端的目录下,生成一个空的文件,标识文件名由用户来指定。一般和“启动作业标识文件”搭配使用。 这里需要注意的是,不要和传输的文件混淆,例如传输文件为“finish.txt”,但如果作业成功标识文件也设置为“finish.txt”,这样会造成这两个文件相互覆盖。 过滤器 使用CDM迁移文件的时候,可以使用过滤器来过滤文件。支持通过通配符或时间过滤器来过滤文件。 选择通配符时,CDM只迁移满足过滤条件的目录或文件。 选择时间过滤器时,只有文件的修改时间晚于输入的时间才会被传输。 例如用户的“/table/”目录下存储了很多数据表的目录,并且按天进行了划分DRIVING_BEHAVIOR_20180101~DRIVING_BEHAVIOR_20180630,保存了DRIVING_BEHAVIOR从1月到6月的所有数据。如果只想迁移DRIVING_BEHAVIOR的3月份的表数据,那么需要在作业第一步指定源目录为“/table”,过滤类型选择“通配符”,然后指定“路径过滤器”为“DRIVING_BEHAVIOR_201803*”。
-
文件格式问题解决方法 数据库的数据导出到 CS V文件,由于数据中含有分隔符逗号,造成导出的CSV文件中数据混乱。 CDM提供了以下几种解决方法: 指定字段分隔符 使用数据库中不存在的字符,或者是极少见的不可打印字符来作为字段分隔符。例如可以在目的端指定“字段分隔符”为“%01”,这样导出的字段分隔符就是“\u0001”,详情可见表1。 使用包围符 在目的端作业参数中开启“使用包围符”,这样数据库中如果字段包含了字段分隔符,在导出到CSV文件的时候,CDM会使用包围符将该字段括起来,使之作为一个字段的值写入CSV文件。 数据库的数据包含换行符 场景:使用CDM先将MySQL中的某张表(表的某个字段值中包含了换行符\n)导出到CSV格式的文件中,然后再使用CDM将导出的CSV文件导入到 MRS HBase,发现导出的CSV文件中出现了数据被截断的情况。 解决方法:指定换行符。 在使用CDM将MySQL的表数据导出到CSV文件时,指定目的端的换行符为“%01”(确保这个值不会出现在字段值中),这样导出的CSV文件中换行符就是“%01”。然后再使用CDM将CSV文件导入到MRS HBase时,指定源端的换行符为“%01”,这样就避免了数据被截断的问题。
-
二进制格式 如果想要在文件系统间按原样复制文件,则可以选择二进制格式。二进制格式传输文件到文件的速率高、性能稳定,且不需要在作业第二步进行字段匹配。 文件传输的目录结构 CDM的文件传输,支持单文件,也支持一次传输目录下所有的文件。传输到目的端后,目录结构会保持原样。 增量迁移文件 使用CDM进行二进制传输文件时,目的端有一个参数“重复文件处理方式”,可以用作文件的增量迁移,具体请参见文件增量迁移。 增量迁移文件的时候,选择“重复文件处理方式”为“跳过重复文件”,这样如果源端有新增的文件,或者是迁移过程中出现了失败,只需要再次运行任务,已经迁移过的文件就不会再次迁移。 写入到临时文件 二进制迁移文件时候,可以在目的端指定是否写入到临时文件。如果指定了该参数,在文件复制过程中,会将文件先写入到一个临时文件中,迁移成功后,再进行rename或move操作,在目的端恢复文件。 生成文件MD5值 对每个传输的文件都生成一个MD5值,并将该值记录在一个新文件中,新文件以“.md5”作为后缀,并且可以指定MD5值生成的目录。
-
JSON格式 这里主要介绍JSON文件格式的以下内容: CDM支持解析的JSON类型 记录节点 从JSON文件复制数据 CDM支持解析的JSON类型:JSON对象、JSON数组。 JSON对象:JSON文件包含单个对象,或者以行分隔/串连的多个对象。 单一对象JSON { "took" : 190, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 } 行分隔的JSON对象 {"took" : 188, "timed_out" : false, "total" : 1000003, "max_score" : 1.0 } {"took" : 189, "timed_out" : false, "total" : 1000004, "max_score" : 1.0 } 串连的JSON对象 { "took": 190, "timed_out": false, "total": 1000001, "max_score": 1.0 } { "took": 191, "timed_out": false, "total": 1000002, "max_score": 1.0 } JSON数组:JSON文件是包含多个JSON对象的数组。 [{ "took" : 190, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 }, { "took" : 191, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 }] 记录节点 记录数据的根节点。该节点对应的数据为JSON数组,CDM会以同一模式从该数组中提取数据。多层嵌套的JSON节点以字符“.”分割。 从JSON文件复制数据 示例一 从行分隔/串连的多个对象中提取数据。JSON文件包含了多个JSON对象,例如: { "took": 190, "timed_out": false, "total": 1000001, "max_score": 1.0 } { "took": 191, "timed_out": false, "total": 1000002, "max_score": 1.0 } { "took": 192, "timed_out": false, "total": 1000003, "max_score": 1.0 } 如果您想要从该JSON对象中提取数据,使用以下格式写入到数据库,只需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON对象”,然后在作业第二步进行字段匹配即可。 表2 示例 took timedOut total maxScore 190 false 1000001 1.0 191 false 1000002 1.0 192 false 1000003 1.0 示例二 从记录节点中提取数据。JSON文件包含了单个的JSON对象,但是其中有效的数据在一个数据节点下,例如: { "took": 190, "timed_out": false, "hits": { "total": 1000001, "max_score": 1.0, "hits": [{ "_id": "650612", "_source": { "name": "tom", "books": ["book1","book2","book3"] } }, { "_id": "650616", "_source": { "name": "tom", "books": ["book1","book2","book3"] } }, { "_id": "650618", "_source": { "name": "tom", "books": ["book1","book2","book3"] } }] } } 如果想以如下格式写入到数据库,则需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON对象”,并且指定记录节点为“hits.hits”,然后在作业第二步进行字段匹配。 表3 示例 ID SourceName SourceBooks 650612 tom ["book1","book2","book3"] 650616 tom ["book1","book2","book3"] 650618 tom ["book1","book2","book3"] 示例三 从JSON数组中提取数据。JSON文件是包含了多个JSON对象的JSON数组,例如: [{ "took" : 190, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 }, { "took" : 191, "timed_out" : false, "total" : 1000002, "max_score" : 1.0 }] 如果想以如下格式写入到数据库,需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON数组”,然后在作业第二步进行字段匹配。 表4 示例 took timedOut total maxScore 190 false 1000001 1.0 191 false 1000002 1.0 示例四 在解析JSON文件的时候搭配转换器。在示例二前提下,想要把hits.max_score字段附加到所有记录中,即以如下格式写入到数据库中: 表5 示例 ID SourceName SourceBooks MaxScore 650612 tom ["book1","book2","book3"] 1.0 650616 tom ["book1","book2","book3"] 1.0 650618 tom ["book1","book2","book3"] 1.0 则需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON对象”,并且指定记录节点为“hits.hits”,然后在作业第二步添加转换器,操作步骤如下: 单击添加字段,新增一个字段。 图2 添加字段 在添加的新字段后面,单击添加字段转换器。 图3 添加字段转换器 创建“表达式转换”的转换器,表达式输入“1.0”,然后保存。 图4 配置字段转换器
-
二进制格式 如果想要在文件系统间按原样复制文件,则可以选择二进制格式。二进制格式传输文件到文件的速率高、性能稳定,且不需要在作业第二步进行字段匹配。 文件传输的目录结构 CDM的文件传输,支持单文件,也支持一次传输目录下所有的文件。传输到目的端后,目录结构会保持原样。 增量迁移文件 使用CDM进行二进制传输文件时,目的端有一个参数“重复文件处理方式”,可以用作文件的增量迁移,具体请参见文件增量迁移。 增量迁移文件的时候,选择“重复文件处理方式”为“跳过重复文件”,这样如果源端有新增的文件,或者是迁移过程中出现了失败,只需要再次运行任务,已经迁移过的文件就不会再次迁移。 写入到临时文件 二进制迁移文件时候,可以在目的端指定是否写入到临时文件。如果指定了该参数,在文件复制过程中,会将文件先写入到一个临时文件中,迁移成功后,再进行rename或move操作,在目的端恢复文件。 生成文件MD5值 对每个传输的文件都生成一个MD5值,并将该值记录在一个新文件中,新文件以“.md5”作为后缀,并且可以指定MD5值生成的目录。
-
文件格式问题解决方法 数据库的数据导出到CSV文件,由于数据中含有分隔符逗号,造成导出的CSV文件中数据混乱。 CDM提供了以下几种解决方法: 指定字段分隔符 使用数据库中不存在的字符,或者是极少见的不可打印字符来作为字段分隔符。例如可以在目的端指定“字段分隔符”为“%01”,这样导出的字段分隔符就是“\u0001”,详情可见表1。 使用包围符 在目的端作业参数中开启“使用包围符”,这样数据库中如果字段包含了字段分隔符,在导出到CSV文件的时候,CDM会使用包围符将该字段括起来,使之作为一个字段的值写入CSV文件。 数据库的数据包含换行符 场景:使用CDM先将MySQL中的某张表(表的某个字段值中包含了换行符\n)导出到CSV格式的文件中,然后再使用CDM将导出的CSV文件导入到MRS HBase,发现导出的CSV文件中出现了数据被截断的情况。 解决方法:指定换行符。 在使用CDM将MySQL的表数据导出到CSV文件时,指定目的端的换行符为“%01”(确保这个值不会出现在字段值中),这样导出的CSV文件中换行符就是“%01”。然后再使用CDM将CSV文件导入到MRS HBase时,指定源端的换行符为“%01”,这样就避免了数据被截断的问题。
-
文件格式的公共参数 启动作业标识文件 这个主要用于自动化场景中,CDM配置了定时任务,周期去读取源端文件,但此时源端的文件正在生成中,CDM此时读取会造成重复写入或者是读取失败。所以,可以在源端作业参数中指定启动作业标识文件为“ok.txt”,在源端生成文件成功后,再在文件目录下生成“ok.txt”,这样CDM就能读取到完整的文件。 另外,可以设置超时时间,在超时时间内,CDM会周期去查询标识文件是否存在,超时后标识文件还不存在的话,则作业任务失败。 启动作业标识文件本身不会被迁移。 作业成功标识文件 文件系统为目的端的时候,当任务成功时,在目的端的目录下,生成一个空的文件,标识文件名由用户来指定。一般和“启动作业标识文件”搭配使用。 这里需要注意的是,不要和传输的文件混淆,例如传输文件为“finish.txt”,但如果作业成功标识文件也设置为“finish.txt”,这样会造成这两个文件相互覆盖。 过滤器 使用CDM迁移文件的时候,可以使用过滤器来过滤文件。支持通过通配符或时间过滤器来过滤文件。 选择通配符时,CDM只迁移满足过滤条件的目录或文件。 选择时间过滤器时,只有文件的修改时间晚于输入的时间才会被传输。 例如用户的“/table/”目录下存储了很多数据表的目录,并且按天进行了划分DRIVING_BEHAVIOR_20180101~DRIVING_BEHAVIOR_20180630,保存了DRIVING_BEHAVIOR从1月到6月的所有数据。如果只想迁移DRIVING_BEHAVIOR的3月份的表数据,那么需要在作业第一步指定源目录为“/table”,过滤类型选择“通配符”,然后指定“路径过滤器”为“DRIVING_BEHAVIOR_201803*”。
-
JSON格式 这里主要介绍JSON文件格式的以下内容: CDM支持解析的JSON类型 记录节点 从JSON文件复制数据 CDM支持解析的JSON类型:JSON对象、JSON数组。 JSON对象:JSON文件包含单个对象,或者以行分隔/串连的多个对象。 单一对象JSON { "took" : 190, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 } 行分隔的JSON对象 {"took" : 188, "timed_out" : false, "total" : 1000003, "max_score" : 1.0 } {"took" : 189, "timed_out" : false, "total" : 1000004, "max_score" : 1.0 } 串连的JSON对象 { "took": 190, "timed_out": false, "total": 1000001, "max_score": 1.0 } { "took": 191, "timed_out": false, "total": 1000002, "max_score": 1.0 } JSON数组:JSON文件是包含多个JSON对象的数组。 [{ "took" : 190, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 }, { "took" : 191, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 }] 记录节点 记录数据的根节点。该节点对应的数据为JSON数组,CDM会以同一模式从该数组中提取数据。多层嵌套的JSON节点以字符“.”分割。 从JSON文件复制数据 示例一 从行分隔/串连的多个对象中提取数据。JSON文件包含了多个JSON对象,例如: { "took": 190, "timed_out": false, "total": 1000001, "max_score": 1.0 } { "took": 191, "timed_out": false, "total": 1000002, "max_score": 1.0 } { "took": 192, "timed_out": false, "total": 1000003, "max_score": 1.0 } 如果您想要从该JSON对象中提取数据,使用以下格式写入到数据库,只需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON对象”,然后在作业第二步进行字段匹配即可。 表2 示例 took timedOut total maxScore 190 false 1000001 1.0 191 false 1000002 1.0 192 false 1000003 1.0 示例二 从记录节点中提取数据。JSON文件包含了单个的JSON对象,但是其中有效的数据在一个数据节点下,例如: { "took": 190, "timed_out": false, "hits": { "total": 1000001, "max_score": 1.0, "hits": [{ "_id": "650612", "_source": { "name": "tom", "books": ["book1","book2","book3"] } }, { "_id": "650616", "_source": { "name": "tom", "books": ["book1","book2","book3"] } }, { "_id": "650618", "_source": { "name": "tom", "books": ["book1","book2","book3"] } }] } } 如果想以如下格式写入到数据库,则需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON对象”,并且指定记录节点为“hits.hits”,然后在作业第二步进行字段匹配。 表3 示例 ID SourceName SourceBooks 650612 tom ["book1","book2","book3"] 650616 tom ["book1","book2","book3"] 650618 tom ["book1","book2","book3"] 示例三 从JSON数组中提取数据。JSON文件是包含了多个JSON对象的JSON数组,例如: [{ "took" : 190, "timed_out" : false, "total" : 1000001, "max_score" : 1.0 }, { "took" : 191, "timed_out" : false, "total" : 1000002, "max_score" : 1.0 }] 如果想以如下格式写入到数据库,需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON数组”,然后在作业第二步进行字段匹配。 表4 示例 took timedOut total maxScore 190 false 1000001 1.0 191 false 1000002 1.0 示例四 在解析JSON文件的时候搭配转换器。在示例二前提下,想要把hits.max_score字段附加到所有记录中,即以如下格式写入到数据库中: 表5 示例 ID SourceName SourceBooks MaxScore 650612 tom ["book1","book2","book3"] 1.0 650616 tom ["book1","book2","book3"] 1.0 650618 tom ["book1","book2","book3"] 1.0 则需要在作业第一步指定文件格式为“JSON格式”,指定JSON类型为“JSON对象”,并且指定记录节点为“hits.hits”,然后在作业第二步添加转换器,操作步骤如下: 单击添加字段,新增一个字段。 图2 添加字段 在添加的新字段后面,单击添加字段转换器。 图3 添加字段转换器 创建“表达式转换”的转换器,表达式输入“1.0”,然后保存。 图4 配置字段转换器
-
表达式转换 使用JSP表达式语言(Expression Language)对当前字段或整行数据进行转换。JSP表达式语言可以用来创建算术和逻辑表达式。在表达式内可以使用整型数,浮点数,字符串,常量true、false和null。 数据进行转换过程中,替换内容包含特殊字符时,需要先使用\将该字符转义成普通字符。 表达式支持以下两个环境变量: value:当前字段值。 row:当前行,数组类型。 表达式支持的工具类用法罗列如下,未列出即表示不支持: 如果当前字段为字符串类型,将字符串全部转换为小写,例如将“aBC”转换为“abc”。 表达式:StringUtils.lowerCase(value) 将当前字段的字符串全部转为大写。 表达式:StringUtils.upperCase(value) 如果想将第1个日期字段格式从“2018-01-05 15:15:05”转换为“20180105”。 表达式:DateUtils.format(DateUtils.parseDate(row[0],"yyyy-MM-dd HH:mm:ss"),"yyyyMMdd") 如果想将时间戳转换成“yyyy-MM-dd hh:mm:ss”格式的日期字符串的类型,例如字段值为“1701312046588”,转换后为“2023-11-30 10:40:46”。 表达式:DateUtils.format(NumberUtils.toLong(value),"yyyy-MM-dd HH:mm:ss") 如果想将“yyyy-MM-dd hh:mm:ss”格式的日期字符串转换成时间戳的类型。 表达式:DateUtils.getTime(DateUtils.parseDate(value,"yyyy-MM-dd hh:mm:ss")) 如果当前字段值为“yyyy-MM-dd”格式的日期字符串,需要截取年,例如字段值为“2017-12-01”,转换后为“2017”。 表达式:StringUtils.substringBefore(value,"-") 如果当前字段值为数值类型,转换后值为当前值的两倍。 表达式:value*2 如果当前字段值为“true”,转换后为“Y”,其它值则转换后为“N”。 表达式:value=="true"?"Y":"N" 如果当前字段值为字符串类型,当为空时,转换为“Default”,否则不转换。 表达式:empty value? "Default":value 如果想将日期字段格式从“2018/01/05 15:15:05”转换为“2018-01-05 15:15:05”。 表达式:DateUtils.format(DateUtils.parseDate(value,"yyyy/MM/dd HH:mm:ss"),"yyyy-MM-dd HH:mm:ss") 获取一个36位的UUID(Universally Unique Identifier,通用唯一识别码)。 表达式:CommonUtils.randomUUID() 如果当前字段值为字符串类型,将首字母转换为大写,例如将“cat”转换为“Cat”。 表达式:StringUtils.capitalize(value) 如果当前字段值为字符串类型,将首字母转换为小写,例如将“Cat”转换为“cat”。 表达式:StringUtils.uncapitalize(value) 如果当前字段值为字符串类型,使用空格填充为指定长度,并且将字符串居中,当字符串长度不小于指定长度时不转换,例如将“ab”转换为长度为4的“ab”。 表达式:StringUtils.center(value,4) 删除字符串末尾的一个换行符(包括“\n”、“\r”或者“\r\n”),例如将“abc\r\n\r\n”转换为“abc\r\n”。 表达式:StringUtils.chomp(value) 如果字符串中包含指定的字符串,则返回布尔值true,否则返回false。例如“abc”中包含“a”,则返回true。 表达式:StringUtils.contains(value,"a") 如果字符串中包含指定字符串的任一字符,则返回布尔值true,否则返回false。例如“zzabyycdxx”中包含“z”或“a”任意一个,则返回true。 表达式:StringUtils.containsAny(value,"za") 如果字符串中不包含指定的所有字符,则返回布尔值true,包含任意一个字符则返回false。例如“abz”中包含“xyz”里的任意一个字符,则返回false。 表达式:StringUtils.containsNone(value,"xyz") 如果当前字符串只包含指定字符串中的字符,则返回布尔值true,包含任意一个其它字符则返回false。例如“abab”只包含“abc”中的字符,则返回true。 表达式:StringUtils.containsOnly(value,"abc") 如果字符串为空或null,则转换为指定的字符串,否则不转换。例如将空字符转换为null。 表达式:StringUtils.defaultIfEmpty(value,null) 如果字符串以指定的后缀结尾(包括大小写),则返回布尔值true,否则返回false。例如“abcdef”后缀不为null,则返回false。 表达式:StringUtils.endsWith(value,null) 如果字符串和指定的字符串完全一样(包括大小写),则返回布尔值true,否则返回false。例如比较字符串“abc”和“ABC”,则返回false。 表达式:StringUtils.equals(value,"ABC") 从字符串中获取指定字符串的第一个索引,没有则返回整数-1。例如从“aabaabaa”中获取“ab”的第一个索引1。 表达式:StringUtils.indexOf(value,"ab") 从字符串中获取指定字符串的最后一个索引,没有则返回整数-1。例如从“aFkyk”中获取“k”的最后一个索引4。 表达式:StringUtils.lastIndexOf(value,"k") 从字符串中指定的位置往后查找,获取指定字符串的第一个索引,没有则转换为“-1”。例如“aabaabaa”中索引3的后面,第一个“b”的索引是5。 表达式:StringUtils.indexOf(value,"b",3) 从字符串获取指定字符串中任一字符的第一个索引,没有则返回整数-1。例如从“zzabyycdxx”中获取“z”或“a”的第一个索引0。 表达式:StringUtils.indexOfAny(value,"za") 如果字符串仅包含Unicode字符,返回布尔值true,否则返回false。例如“ab2c”中包含非Unicode字符,返回false。 表达式:StringUtils.isAlpha(value) 如果字符串仅包含Unicode字符或数字,返回布尔值true,否则返回false。例如“ab2c”中仅包含Unicode字符和数字,返回true。 表达式:StringUtils.isAlphanumeric(value) 如果字符串仅包含Unicode字符、数字或空格,返回布尔值true,否则返回false。例如“ab2c”中仅包含Unicode字符和数字,返回true。 表达式:StringUtils.isAlphanumericSpace(value) 如果字符串仅包含Unicode字符或空格,返回布尔值true,否则返回false。例如“ab2c”中包含Unicode字符和数字,返回false。 表达式:StringUtils.isAlphaSpace(value) 如果字符串仅包含ASCII可打印字符,返回布尔值true,否则返回false。例如“!ab-c~”返回true。 表达式:StringUtils.isAsciiPrintable(value) 如果字符串为空或null,返回布尔值true,否则返回false。 表达式:StringUtils.isEmpty(value) 如果字符串中仅包含Unicode数字,返回布尔值true,否则返回false。 表达式:StringUtils.isNumeric(value) 获取字符串最左端的指定长度的字符,例如获取“abc”最左端的2位字符“ab”。 表达式:StringUtils.left(value,2) 获取字符串最右端的指定长度的字符,例如获取“abc”最右端的2位字符“bc”。 表达式:StringUtils.right(value,2) 将指定字符串拼接至当前字符串的左侧,需同时指定拼接后的字符串长度,如果当前字符串长度不小于指定长度,则不转换。例如将“yz”拼接到“bat”左侧,拼接后长度为8,则转换后为“yzyzybat”。 表达式:StringUtils.leftPad(value,8,"yz") 将指定字符串拼接至当前字符串的右侧,需同时指定拼接后的字符串长度,如果当前字符串长度不小于指定长度,则不转换。例如将“yz”拼接到“bat”右侧,拼接后长度为8,则转换后为“batyzyzy”。 表达式:StringUtils.rightPad(value,8,"yz") 如果当前字段为字符串类型,获取当前字符串的长度,如果该字符串为null,则返回0。 表达式:StringUtils.length(value) 如果当前字段为字符串类型,删除其中所有的指定字符串,例如从“queued”中删除“ue”,转换后为“qd”。 表达式:StringUtils.remove(value,"ue") 如果当前字段为字符串类型,移除当前字段末尾指定的子字符串。指定的子字符串若不在当前字段的末尾,则不转换,例如移除当前字段“www.domain.com”后的“.com”。 表达式:StringUtils.removeEnd(value,".com") 如果当前字段为字符串类型,移除当前字段开头指定的子字符串。指定的子字符串若不在当前字段的开头,则不转换,例如移除当前字段“www.domain.com”前的“www.”。 表达式:StringUtils.removeStart(value,"www.") 如果当前字段为字符串类型,替换当前字段中所有的指定字符串,例如将“aba”中的“a”用“z”替换,转换后为“zbz”。 表达式:StringUtils.replace(value,"a","z") 替换内容包含特殊字符时,需要先把该字符转义成普通字符,例如,客户想通过该表达式把字符串中 \t 去掉时,需要配置为: StringUtils.replace(value,"\\t","")(即把 \ 再次转义)。 如果当前字段为字符串类型,一次替换字符串中的多个字符,例如将字符串“hello”中的“h”用“j”替换,“o”用“y”替换,转换后为“jelly”。 表达式:StringUtils.replaceChars(value,"ho","jy") 如果字符串以指定的前缀开头(区分大小写),则返回布尔值true,否则返回false,例如当前字符串“abcdef”以“abc”开头,则返回true。 表达式:StringUtils.startsWith(value,"abc") 如果当前字段为字符串类型,去除字段中首、尾处所有指定的字符,例如去除“abcyx”中首尾所有的“x”、“y”、“z”和“b”,转换后为“abc”。 表达式:StringUtils.strip(value,"xyzb") 如果当前字段为字符串类型,去除字段末尾所有指定的字符,例如去除当前字段末尾的“abc”字符串。 表达式:StringUtils.stripEnd(value,"abc") 如果当前字段为字符串类型,去除字段开头所有指定的字符,例如去除当前字段开头的所有空格。 表达式:StringUtils.stripStart(value,null) 如果当前字段为字符串类型,获取字符串指定位置后(索引从0开始,包括指定位置的字符)的子字符串,指定位置如果为负数,则从末尾往前计算位置,末尾第一位为-1。例如获取“abcde”索引为2的字符(即c)及之后的字符串,则转换后为“cde”。 表达式:StringUtils.substring(value,2) 如果当前字段为字符串类型,获取字符串指定区间(索引从0开始,区间起点包括指定位置的字符,区间终点不包含指定位置的字符)的子字符串,区间位置如果为负数,则从末尾往前计算位置,末尾第一位为-1。例如获取“abcde”第2个字符(即c)及之后、第4个字符(即e)之前的字符串,则转换后为“cd”。 表达式:StringUtils.substring(value,2,4) 如果当前字段为字符串类型,获取当前字段里第一个指定字符后的子字符串。例如获取“abcba”中第一个“b”之后的子字符串,转换后为“cba”。 表达式:StringUtils.substringAfter(value,"b") 如果当前字段为字符串类型,获取当前字段里最后一个指定字符后的子字符串。例如获取“abcba”中最后一个“b”之后的子字符串,转换后为“a”。 表达式:StringUtils.substringAfterLast(value,"b") 如果当前字段为字符串类型,获取当前字段里第一个指定字符前的子字符串。例如获取“abcba”中第一个“b”之前的子字符串,转换后为“a”。 表达式:StringUtils.substringBefore(value,"b") 如果当前字段为字符串类型,获取当前字段里最后一个指定字符前的子字符串。例如获取“abcba”中最后一个“b”之前的子字符串,转换后为“abc”。 表达式:StringUtils.substringBeforeLast(value,"b") 如果当前字段为字符串类型,获取嵌套在指定字符串之间的子字符串,没有匹配的则返回null。例如获取“tagabctag”中“tag”之间的子字符串,转换后为“abc”。 表达式:StringUtils.substringBetween(value,"tag") 如果当前字段为字符串类型,删除当前字符串两端的控制字符(char≤32),例如删除字符串前后的空格。 表达式:StringUtils.trim(value) 将当前字符串转换为字节,如果转换失败,则返回0。 表达式:NumberUtils.toByte(value) 将当前字符串转换为字节,如果转换失败,则返回指定值,例如指定值配置为1。 表达式:NumberUtils.toByte(value,1) 将当前字符串转换为Double数值,如果转换失败,则返回0.0d。 表达式:NumberUtils.toDouble(value) 将当前字符串转换为Double数值,如果转换失败,则返回指定值,例如指定值配置为1.1d。 表达式:NumberUtils.toDouble(value,1.1d) 将当前字符串转换为Float数值,如果转换失败,则返回0.0f。 表达式:NumberUtils.toFloat(value) 将当前字符串转换为Float数值,如果转换失败,则返回指定值,例如配置指定值为1.1f。 表达式:NumberUtils.toFloat(value,1.1f) 将当前字符串转换为Int数值,如果转换失败,则返回0。 表达式:NumberUtils.toInt(value) 将当前字符串转换为Int数值,如果转换失败,则返回指定值,例如配置指定值为1。 表达式:NumberUtils.toInt(value,1) 将字符串转换为Long数值,如果转换失败,则返回0。 表达式:NumberUtils.toLong(value) 将当前字符串转换为Long数值,如果转换失败,则返回指定值,例如配置指定值为1L。 表达式:NumberUtils.toLong(value,1L) 将字符串转换为Short数值,如果转换失败,则返回0。 表达式:NumberUtils.toShort(value) 将当前字符串转换为Short数值,如果转换失败,则返回指定值,例如配置指定值为1。 表达式:NumberUtils.toShort(value,1) 将当前IP字符串转换为Long数值,例如将“10.78.124.0”转换为Long数值是“172915712”。 表达式:CommonUtils.ipToLong(value) 从网络读取一个IP与物理地址映射文件,并存放到Map集合,这里的URL是IP与地址映射文件存放地址,例如“http://10.114.205.45:21203/sqoop/IpList.csv”。 表达式:HttpsUtils.downloadMap("url") 将IP与地址映射对象缓存起来并指定一个key值用于检索,例如“ipList”。 表达式:CommonUtils.setCache("ipList",HttpsUtils.downloadMap("url")) 取出缓存的IP与地址映射对象。 表达式:CommonUtils.getCache("ipList") 判断是否有IP与地址映射缓存。 表达式:CommonUtils.cacheExists("ipList") 根据IP取出对应的详细地址:国家_省份_城市_运营商,例如“1xx.78.124.0”对应的地址为“中国_广东_深圳_电信”,取不到对应地址则默认“**_**_**_**”。如果需要,可通过StringUtil类表达式对地址进行进一步拆分。 表达式:CommonUtils.getMapValue(CommonUtils.ipToLong(value),CommonUtils.cacheExists("ipLis")?CommonUtils.getCache("ipLis"):CommonUtils.setCache("ipLis",HttpsUtils.downloadMap("url"))) 根据指定的偏移类型(month/day/hour/minute/second)及偏移量(正数表示增加,负数表示减少),将指定格式的时间转换为一个新时间,例如将“2019-05-21 12:00:00”增加8个小时。 表达式:DateUtils.getCurrentTimeByZone("yyyy-MM-dd HH:mm:ss",value, "hour", 8) 如果value值为空或者null时,则返回字符串“aaa”,否则返回value。 表达式:StringUtils.defaultIfEmpty(value,"aaa")
-
约束限制 作业源端开启“使用SQL语句”参数时不支持配置转换器。 如果在字段映射界面,CDM通过获取样值的方式无法获得所有列(例如从HBase/CloudTable/MongoDB导出数据时,CDM有较大概率无法获得所有列),则可以单击后选择“添加新字段”来手动增加,确保导入到目的端的数据完整。 关系数据库、Hive、MRS Hudi及 DLI 做源端时,不支持获取样值功能。 SQLServer作为目的端数据源时,不支持timestamp类型字段的写入,需修改为其他时间类型字段写入(如datetime)。 当作业源端为OBS、迁移CSV文件时,并且配置“解析首行为列名”参数的场景下显示列名。 当使用二进制格式进行文件到文件的迁移时,没有配置字段转换器这一步。 自动创表场景下,需在目的端表中提前手动新增字段,再在字段映射里新增字段。 添加完字段后,新增的字段在界面不显示样值,不会影响字段值的传输,CDM会将字段值直接写入目的端。 如果字段映射关系不正确,您可以通过拖拽字段、单击对字段批量映射两种方式来调整字段映射关系。 创建表达式转换器时,表达式的功能是对该字段的数据进行处理,故不建议使用时间宏,如需使用,请根据以下场景处理(源端是文件类的配置时仅支持方式一): 方式一:新建表达式转换器时,表达式需要用''包围。 ${dateformat(yyyy-MM-dd)}不加引号使用时,解析成2017-10-16之后还会进行运算,将'-'识别为减号,导致结果为1991,须使用'${dateformat(yyyy-MM-dd)}',即'2017-10-16'。 图2 使用''包围表达式 方式二:源字段中新增自定义字段,在样值中填写时间宏变量,重新进行字段映射处理。 图3 源字段新增自定义字段 如果是导入到 数据仓库 服务(DWS),则还需在目的字段中选择分布列,建议按如下顺序选取分布列: 有主键可以使用主键作为分布列。 多个数据段联合做主键的场景,建议设置所有主键作为分布列。 在没有主键的场景下,如果没有选择分布列,DWS会默认第一列作为分布列,可能会有数据倾斜风险。
-
时间宏变量和定时任务配合完成增量同步 这里列举两个简单的使用场景: 数据库表中存在表示时间的列DS,类型为“varchar(30)”,插入的时间格式类似于“2017-xx-xx”。 定时任务中,重复周期为1天,每天的凌晨0点执行定时任务。配置“Where子句”为DS='${dateformat(yyyy-MM-dd,-1,DAY)}',这样就可以在每天的凌晨0点导出前一天产生的所有数据。 数据库表中存在表示时间的列time,类型为“Number”,插入的时间格式为时间戳。 定时任务中,重复周期为1天,每天的凌晨0点执行定时任务。配置“Where子句”为time between ${timestamp(-1,DAY)} and ${timestamp()},这样就可以在每天的凌晨0点导出前一天产生的所有数据。 其它的配置方式原理相同。
-
路径和表名的时间宏变量 如图1所示,如果将: 源端的“表名”配置为“CDM_/${dateformat(yyyy-MM-dd)}”。 目的端的“写入目录”配置为“/opt/ttxx/${timestamp()}”。 经过宏定义转换,这个作业表示:将Oracle数据库的“SQOOP.CDM_20171016”表中数据,迁移到HDFS的“/opt/ttxx/1508115701746”目录中。 图1 源表名和写入目录配置为时间宏变量 目前也支持一个表名或路径名中有多个宏定义变量,例如“/opt/ttxx/${dateformat(yyyy-MM-dd)}/${timestamp()}”,经过转换后为“/opt/ttxx/2017-10-16/1508115701746”。
-
Where子句中的时间宏变量 以SQOOP.CDM_20171016表为例,该表中存在表示时间的列DS,如图2所示。 图2 表数据 假设当前时间为“2017-10-16”,要导出前一天的数据(即DS=‘2017-10-15’),则可以在创建作业时配置“Where子句”为DS='${dateformat(yyyy-MM-dd,-1,DAY)}',即可将符合DS=‘2017-10-15’条件的数据导出。
-
时间变量宏定义具体展示 假设当前时间为“2017-10-16 09:00:00”,时间变量宏定义具体如表1所示。 表中示例实际使用时必须嵌在''中使用,比如需要以yyyy-MM-dd格式返回当前时间时,参数为'${dateformat(yyyy-MM-dd)}'。 表1 时间变量宏定义具体展示 宏变量 含义 实际显示效果 ${dateformat(yyyy-MM-dd)} 以yyyy-MM-dd格式返回当前时间。 2017-10-16 ${dateformat(yyyy/MM/dd)} 以yyyy/MM/dd格式返回当前时间。 2017/10/16 ${dateformat(yyyy_MM_dd HH:mm:ss)} 以yyyy_MM_dd HH:mm:ss格式返回当前时间。 2017_10_16 09:00:00 ${dateformat(yyyy-MM-dd HH:mm:ss, -1, DAY)} 以yyyy-MM-dd HH:mm:ss格式返回时间,时间为当前时间的前一天。 2017-10-15 09:00:00 ${dateformat(yyyy-MM-dd, -1, DAY)} 00:00:00 以yyyy-MM-dd HH:mm:ss格式返回时间,时间为当前时间的前一天0点。 2017-10-15 00:00:00 ${dateformat(yyyy-MM-dd, -1, DAY)} 12:00:00 以yyyy-MM-dd HH:mm:ss格式返回时间,时间为当前时间的前一天12点。 2017-10-15 12:00:00 ${dateformat(yyyy-MM-dd, -N, DAY)} 00:00:00 以yyyy-MM-dd HH:mm:ss格式返回时间,时间为当前时间的前N天的0点。 N为3时: 2017-10-13 00:00:00 ${dateformat(yyyy-MM-dd, -N, DAY)} 12:00:00 以yyyy-MM-dd HH:mm:ss格式返回时间,时间为当前时间的前N天的12点。 N为3时: 2017-10-13 12:00:00 ${timestamp()} 返回当前时间的时间戳,即1970年1月1日(00:00:00 GMT)到当前时间的毫秒数。 1508115600000 ${timestamp(-10, MINUTE)} 返回当前时间点10分钟前的时间戳。 1508115000000 ${timestamp(dateformat(yyyyMMdd))} 返回今天0点的时间戳。 1508083200000 ${timestamp(dateformat(yyyyMMdd,-1,DAY))} 返回昨天0点的时间戳。 1507996800000 ${timestamp(dateformat(yyyyMMddHH))} 返回当前整小时的时间戳。 1508115600000
-
timestamp timestamp支持两种形式的参数: timestamp() 返回当前时间的时间戳,即从1970年到现在的毫秒数,如1508078516286。 timestamp(dateOffset, dateType) 返回经过时间偏移后的时间戳,“dateOffset”和“dateType”表示日期的偏移量以及偏移量的类型。 例如当前日期为“2017-10-16 09:00:00”,则“timestamp(-10, MINUTE)”返回当前时间点10分钟前的时间戳,即“1508115000000”。
更多精彩内容
CDN加速
GaussDB
文字转换成语音
免费的服务器
如何创建网站
域名网站购买
私有云桌面
云主机哪个好
域名怎么备案
手机云电脑
SSL证书申请
云点播服务器
免费OCR是什么
电脑云桌面
域名备案怎么弄
语音转文字
文字图片识别
云桌面是什么
网址安全检测
网站建设搭建
国外CDN加速
SSL免费证书申请
短信批量发送
图片OCR识别
云数据库MySQL
个人域名购买
录音转文字
扫描图片识别文字
OCR图片识别
行驶证识别
虚拟电话号码
电话呼叫中心软件
怎么制作一个网站
Email注册网站
华为VNC
图像文字识别
企业网站制作
个人网站搭建
华为云计算
免费租用云托管
云桌面云服务器
ocr文字识别免费版
HTTPS证书申请
图片文字识别转换
国外域名注册商
使用免费虚拟主机
云电脑主机多少钱
鲲鹏云手机
短信验证码平台
OCR图片文字识别
SSL证书是什么
申请企业邮箱步骤
免费的企业用邮箱
云免流搭建教程
域名价格