用 Pig Latin 为每组编写一个文件
Posted
技术标签:
【中文标题】用 Pig Latin 为每组编写一个文件【英文标题】:Writing one file per group in Pig Latin 【发布时间】:2012-04-30 18:14:07 【问题描述】:问题: 我有许多包含 Apache Web 服务器日志条目的文件。这些条目不是按日期时间顺序排列的,而是分散在文件中的。我正在尝试使用 Pig 读取一天的文件,按日期时间对日志条目进行分组和排序,然后将它们写入以它包含的条目的日期和时间命名的文件。
设置: 导入文件后,我将使用 Regex 获取日期字段,然后将其截断为小时。这会产生一个集合,该集合在一个字段中具有记录,而在另一个字段中将日期截断为小时。从这里开始,我在日期-小时字段上进行分组。
第一次尝试: 我的第一个想法是在使用 FOREACH 遍历我的组时使用 STORE 命令,并很快发现使用 Pig 并不酷。
第二次尝试: 我的第二次尝试是在 piggybank 中使用 MultiStorage() 方法,在我查看文件之前效果很好。问题是 MulitStorage 想要将所有字段写入文件,包括我用来分组的字段。我真正想要的只是写入文件的原始记录。
问题: 那么......我是否将 Pig 用于它不打算用于的东西,或者有更好的方法让我使用 Pig 来解决这个问题?既然我有这个问题,我将处理一个简单的代码示例来进一步解释我的问题。一旦我有了它,我会在这里发布。提前致谢。
【问题讨论】:
【参考方案1】:开箱即用,Pig 没有很多功能。它完成了基本的工作,但更多时候我发现自己必须编写自定义 UDF 或加载/存储函数才能从 95% 的路径到 100% 的路径。我通常觉得这是值得的,因为编写一个小型存储函数比编写整个 MapReduce 程序要少很多 Java。
你的第二次尝试真的很接近我会做的事情。您应该复制/粘贴MultiStorage
的源代码或使用继承作为起点。然后,修改putNext
方法以去除组值,但仍写入该文件。不幸的是,Tuple
没有remove
或delete
方法,因此您必须重写整个元组。或者,如果您只有原始字符串,只需将其拉出并输出包裹在 Tuple
中的内容。
一些关于编写加载/存储函数的一般文档,以防您需要更多帮助:http://pig.apache.org/docs/r0.10.0/udf.html#load-store-functions
【讨论】:
感谢 orangeoctopus,这正是我想要的。我已经编写了一个自定义 eval UDF,我可以假设编写自定义加载/存储 UDF 的过程是相似的吗?我对 Java 有点陌生……边走边学。 会有点复杂,但不会那么糟糕。开源最好的部分之一是能够从执行类似操作的事物中复制/粘贴(在学习意义上)。我建议您尝试一下,如果遇到问题,请回来并发布一个新问题!我认识很多具有 SQL 背景的人,但对 Java 一点也不了解。 --首先,我将MulitStorage的源码复制到StoreUDF/MultiStorageUDF.java中。 --然后我将类和构造函数重命名为MultiStorageUDF,并将包更改为MyUDFs。 --然后我将 pig.jar 复制到 StoreUDF --接下来我做了“javac -cp pig.jar MultiStorageUDF.java”。 --然后我打开了一个目录并运行了“jar -cf MyUDFs.jar StoreUDF”。在我的 .pig 文件中,我有 -在我的 pig 文件中,我将 jar 注册为“register MyUDFs.jar;”并调用类似“...USING MyUDFs.MultiStorageUDF('$OUTPUT', '0');”的函数当我运行我的工作时,我收到一条错误消息,上面写着“错误 1070:无法使用导入解析 MyUDFs.MultiStorageUDF:”。我究竟做错了什么?我的 UDF 编译得很好,据我所知,我指的是正确的。 我刚刚想通了。包含我的 .java 文件和 pig.jar 文件的目录名称必须与我的包同名。看起来像 Java 基础知识。以上是关于用 Pig Latin 为每组编写一个文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Pig Latin 中每行加载一个带有 JSON 数组的文件