我有来自IIS的日志文件存储在hdfs中,但是由于webserver配置,一些日志没有所有列,或者它们以不同的顺序出现。我想生成具有公共模式的文件,以便我可以在它们上面定义一个Hive表。
好日志示例:
#Fields: date time s-ip cs-method cs-uri-stem useragent
2013-07-16 00:00:00 10.1.15.8 GET /common/viewFile/1232 Mozilla/5.0+Chrome/27.0.1453.116
缺少列的示例日志(缺少cs-method和useragent):
#Fields: date time s-ip cs-uri-stem
2013-07-16 00:00:00 10.1.15.8 /common/viewFile/1232
需要将缺少列的日志映射到完整模式,如下所示:
#Fields: date time s-ip cs-method cs-uri-stem useragent
2013-07-16 00:00:00 10.1.15.8 null /common/viewFile/1232 null
错误日志可以启用任何列的组合,顺序不同。
如何根据日志文件中的Fields行将可用列映射到完整模式?
编辑: 通常我会通过将列模式定义为dict映射列名到索引来实现此目的。即:col ['date'] = 0 col ['time'] = 1等然后我会从文件中读取#Fields行并解析出已启用的列并生成标题dict映射头名称到文件中的列索引。然后,对于剩余的数据行,我通过索引知道它的标题,通过header = column name将其映射到我的列模式,并以正确的顺序生成新行,插入带有空数据的缺失列。我的问题是我不明白如何在hadoop中执行此操作,因为每个地图单独执行,因此如何与每个地图共享#Fields信息?
答案 0 :(得分:1)
您可以使用this将标头应用于创建地图的列。从那里你可以使用UDF,如:
<强> myudf.py 强>
#!/usr/bin/python
@outputSchema('newM:map[]')
def completemap(M):
if M is None:
return None
to_add = ['A', 'D', 'F']
for item in to_add:
if item not in M:
M[item] = None
return M
@outputSchema('A:chararray, B:chararray, C:chararray, D:chararray, E:chararray, F:chararray')
def completemap_v2(M):
if M is None:
return (None,
None,
None,
None,
None,
None)
return (M.get('A', None),
M.get('B', None),
M.get('C', None),
M.get('D', None),
M.get('E', None),
M.get('F', None))
将缺少的元组添加到地图中。
示例输入:
csv1.in csv2.in
------- ---------
A|B|C D|E|F
Hello|This|is PLEASE|WORK|FOO
FOO|BAR|BING OR|EVERYTHING|WILL
BANG|BOSH BE|FOR|NAUGHT
示例脚本:
A = LOAD 'tests/csv' USING myudfs.ExampleCSVLoader('\\|') AS (M:map[]);
B = FOREACH A GENERATE FLATTEN(myudf.completemap_v2(M));
输出:
B: {null::A: chararray,null::B: chararray,null::C: chararray,null::D: chararray,null::E: chararray,null::F: chararray}
(,,,,,)
(,,,PLEASE,WORK,FOO)
(,,,OR,EVERYTHING,WILL)
(,,,BE,FOR,NAUGHT)
(,,,,,)
(Hello,This,is,,,)
(FOO,BAR,BING,,,)
(BANG,BOSH,,,,)