我已经查看了本网站上已经提到过的其他类似问题,但没有得到满意的答复。
我是Apache spark和hadoop的全新手。我的问题是我有一个输入文件(35GB),其中包含对在线购物网站商品的多行评论。信息在文件中给出,如下所示:
productId: C58500585F
product: Nun Toy
product/price: 5.99
userId: A3NM6WTIAE
profileName: Heather
helpfulness: 0/1
score: 2.0
time: 1624609
summary: not very much fun
text: Bought it for a relative. Was not impressive.
这是一个审核块。有数千个这样的块由空行分隔。我需要的是productId,userId和score,所以我已经过滤了JavaRDD以获得我需要的行。所以看起来如下:
productId: C58500585F
userId: A3NM6WTIAE
score: 2.0
代码:
SparkConf conf = new SparkConf().setAppName("org.spark.program").setMaster("local");
JavaSparkContext context = new JavaSparkContext(conf);
JavaRDD<String> input = context.textFile("path");
JavaRDD<String> requiredLines = input.filter(new Function<String, Boolean>() {
public Boolean call(String s) throws Exception {
if(s.contains("productId") || s.contains("UserId") || s.contains("score") || s.isEmpty() ) {
return false;
}
return true;
}
});
现在,我需要将这三行读作一个(键,值)对的一部分,我不知道如何。两个评论栏之间只有空行。
我查看了几个网站,但没有找到我的问题的解决方案。 任何人都可以帮我这个吗?非常感谢!如果您需要更多信息,请与我们联系。
答案 0 :(得分:2)
继续我以前的评论,textinputformat.record.delimiter
可以在这里使用。如果唯一的分隔符是空行,则该值应设置为"\n\n"
。
考虑这个测试数据:
productId: C58500585F
product: Nun Toy
product/price: 5.99
userId: A3NM6WTIAE
profileName: Heather
helpfulness: 0/1
score: 2.0
time: 1624609
summary: not very much fun
text: Bought it for a relative. Was not impressive.
productId: ABCDEDFG
product: Teddy Bear
product/price: 6.50
userId: A3NM6WTIAE
profileName: Heather
helpfulness: 0/1
score: 2.0
time: 1624609
summary: not very much fun
text: Second comment.
productId: 12345689
product: Hot Wheels
product/price: 12.00
userId: JJ
profileName: JJ
helpfulness: 1/1
score: 4.0
time: 1624609
summary: Summarized
text: Some text
然后代码(在Scala中)看起来像:
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.io.{LongWritable, Text}
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat
val conf = new Configuration
conf.set("textinputformat.record.delimiter", "\n\n")
val raw = sc.newAPIHadoopFile("test.txt", classOf[TextInputFormat], classOf[LongWritable], classOf[Text], conf)
val data = raw.map(e => {
val m = e._2.toString
.split("\n")
.map(_.split(":", 2))
.filter(_.size == 2)
.map(e => (e(0), e(1).trim))
.toMap
(m("productId"), m("userId"), m("score").toDouble)
})
输出是:
data.foreach(println)
(C58500585F,A3NM6WTIAE,2.0)
(ABCDEDFG,A3NM6WTIAE,2.0)
(12345689,JJ,4.0)
不确定你想要输出的是什么,所以我把它变成了一个3元素的元组。此外,如果您需要,解析逻辑肯定可以提高效率,但这应该可以为您提供一些工作。