簡體   English   中英

如何在Spark和Elasticsearch中迭代hadoop MapWritable

[英]How to iterate over hadoop MapWritable in Spark & Elasticsearch

我對Spark和Scala都不熟悉。 我已經在互聯網上閱讀了一些文章。 我可以使用Spark成功地從Elasticsearch獲取文檔,但是我對如何從文檔中拉取字段感到困惑。

我做了什么

我有33,617個文檔:

import ...

val conf = new JobConf()

conf.set("es.resource", "index-name/type-name")
conf.set("es.nodes", "hostname1:9200,hostname2:9200")
conf.set("es.query", "{...}")

val esRDD = sc.newAPIHadoopRDD(conf, classOf[EsInputFormat[Text, MapWritable]], classOf[Text], classOf[MapWritable])


scala> esRDD.count() // That's GOOD!
res11: Long = 33617

scala> esRDD.take(5).foreach(row => println(row._2))
{@version=1, field1=a, ...}
{@version=1, field1=a, ...} 
{@version=1, field1=b, ...}
{@version=1, field1=b, ...}
{@version=1, field1=b, ...}

問題1:如何打印特定字段。

我不知道如何在Scala中使用org.apache.hadoop.io.MapWritable

// Error!!
scala> esRDD.take(5).foreach(row => println(row._2("field1")))
error: org.apache.hadoop.io.MapWritable does not take parameters
              esRDD.take(5).foreach(row => println(row._2("field1")))

// Oops. null is printed
scala> esRDD.take(5).foreach(row => println(row._2.get("field1")))
null
null
null
null
null

問題2:如何按計數分組

我的最終目標是按field1進行匯總並按如下方式打印其計數:

scala> esRDD.groupBy(???).mapValues(_.size)
Map(a => 2, b => 3) // How to get this output??

但是,我無法弄清楚。

@Mateusz的答案測試

$ bin/spark-shell --master local --jars jars/elasticsearch-spark_2.11-2.2.0.jar

scala> import org.elasticsearch.spark._

scala> val rdd: RDD[(String, Map[String, Any])] = sc.esRDD("index-name/type-name")
<console>:45: error: not found: type RDD
          val rdd: RDD[(String, Map[String, Any])] = sc.esRDD("index-name/type-name")
                   ^

scala> sc.esRDD("index-name/type-name")
java.lang.NoSuchMethodError: scala.Predef$.ArrowAssoc(Ljava/lang/Object;)Ljava/lang/Object;
        at org.elasticsearch.spark.rdd.EsSpark$.esRDD(EsSpark.scala:26)
        at org.elasticsearch.spark.package$SparkContextFunctions.esRDD(package.scala:20)

Elasticsearch-hadoop具有對Spark的本地支持,我建議使用它-API更加簡單:

import org.elasticsearch.spark._        

val rdd: RDD[(String, Map[String, Any])] = sc.esRDD("index-name/type-name")

這是一個簡單的元組rdd,其中鍵是文檔ID,而Map代表您的ES文檔。

您可以將其映射到其他元組中,如下所示:

val mapped = rdd.map{ case(id, doc) => (doc.get("field1").get, 1) }

我輸入1,因為似乎您在其他任何地方都不需要該doc 然后執行一個groupByKey和一個映射:

mapped.groupByKey().map{ case(key,val) => (key, val.size) }

另外,如果僅使用Spark連接器,則不需要整個es-hadoop依賴關系(這相當大),則可以使用elasticsearch-spark

有關更多信息,您可以查看文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM