所以这是data。 结构解释:
CREATE TABLE
products
(product_id
int(11)NOT NULL AUTO_INCREMENT,product_category_id
int(11)NOT NULL,
product_name
varchar(45)NOT NULL,product_description
varchar(255)NOT NULL,product_price
float NOT NULL,
product_image
varchar(255)NOT NULL,PRIMARY KEY(product_id
)) ENGINE = InnoDB AUTO_INCREMENT = 1346 DEFAULT CHARSET = utf8 |
更新:我的环境是Spark 1.6.2和Scala 2.10.5
我希望得到一个按product_name
asc,product_price
desc排序的RDD。
我知道如何将RDD分类为asc:
val p = sc.textFile("products")
val fp = p.filter(r=>r.split(",")(4) !="")
val mfp = fp.map(r=>(r.split(",")(4).toFloat, r)).sortByKey(false).map(r=> (r._2.split(",")(4), r._2.split(",")(2))
现在我只有两个字段:product_price
和product_name
。
我可以进行排序:
mfp.sortBy(r=>(r._1, r._2))
这给了我按名称排序的结果,然后按价格排序,在asc中;
(10,159.99)
(10,159.99)
(10,169.99)
(10,1799.99)
(10,189.0)
(10,199.98)
(10,199.99)
(10,199.99)
(10,1999.99)
(10,269.99)
我需要的是(product_category_id, product_name, product_price)
,在 asc 中按product_category_id
排序,然后product_price
desc 。
我只想要每product_category_id
个前3个产品。
答案 0 :(得分:0)
你几乎得到了它。 RDD sortBy
始终按升序排序。即使你的字段是一个数字,所以你可以通过将它乘以-1得到反向排序。我使用了一个case类来使你的代码更具可读性。
case class Info(product_category_id: Int, product_name: String, product_price: Double)
val rdd = sc.textFile("products").map(line => line.split(",")).filter(!_.isEmpty)
val infos = rdd.map { split =>
Info(
product_category_id = split(1),
product_name = split(2),
product_price = split(4)
)
}
val sorted = infos.sortBy(info => (info.product_category_id, -info.product_price))
坏消息是,这样您就不会按product_category_id
进行分组,因此您无法获得每个类别的前3个产品。幸运的是,Spark mlib
提供了一种方法来完成你想要的,使用有界优先级队列实现。
import org.apache.spark.mllib.rdd.MLPairRDDFunctions._
val keyByCategory = infos.keyBy(_.product_category_id)
val topByKey: RDD[(Int, Array[Info])] = keyByCategory.topByKey(3)(Ordering.by(-_.product_price))
val topWithKeysSorted = topByKey.sortBy(_._1)
答案 1 :(得分:0)
我找到了一个更容易(对我而言)的SparkSQL解决方案,这里是完整的脚本:
val productsRDD = sc.textFile("products").filter(x=>x.split(",")(4)!="")
val productsRDDmap = productsRDD.map(a => (a.split(",")(0).toInt, a.split(",")(1).toInt, a.split(",")(2), a.split(",")(4).toFloat))
val productsRDDmapDF = productsRDDmap.toDF("product_id","product_category_id", "product_name", "product_price")
productsRDDmapDF.registerTempTable("products")
val query = """
select product_id , product_category_id, product_price, row_number() over(partition by product_category_id order by product_price desc) as p_order from products """
val result = sqlContext.sql(query)
result.where("p_order<=3").show(200)