पिछले कुछ घंटों से, मैं अपाचे स्पार्क के साथ एक JSON फ़ाइल को स्काला case class में बदलने की कोशिश कर रहा था।

JSON में निम्नलिखित संरचना है:

{
  "12": {
    "wordA": 1,
    "wordB": 2,
    "wordC": 3
  },
  "13": {
    "wordX": 10,
    "wordY": 12,
    "wordZ": 15
  }
}

पहले प्रयास करें: बिल्ड-अप स्कीमा सेट करें

मैंने कृत्रिम रूप से अपनी स्कीमा बनाने की कोशिश की है:

val schema = new StructType()
   .add("",MapType(StringType, new StructType()
          .add("", StringType)
          .add("", IntegerType)))
val df = session.read
  .option("multiline",true)
  .option("mode", "PERMISSIVE")
  .schema(schema)
  .json(filePath)
df.show()

लेकिन यह स्पष्ट रूप से सही नहीं है क्योंकि मुझे मैदान का नाम देना है।

दूसरा प्रयास: केस क्लास के लिए मैप करें

मैंने case classes बनाने का भी प्रयास किया है, जो थोड़ा अधिक सुरुचिपूर्ण है:

case class KeywordData (keywordsByCode: Map[String, WordAndWeight])

case class WordAndWeight (word: String, weight: Int)

समस्या:

लेकिन किसी भी स्थिति में, df.show() प्रदर्शित करता है:

+----+
|    |
+----+
|null|
+----+

JSON संरचना में हेरफेर करना आसान नहीं है क्योंकि मेरे कॉलम में कोई फिक्स नाम नहीं है। कोई विचार?

अपेक्षित परिणाम

कुंजी के रूप में १२ और १३ के साथ एक नक्शा और सूची [वर्डए, ... वर्डसी] क्रमशः सूची [वर्डएक्स, ..., वर्डजेड] मूल्यों के रूप में

संपादित करें: मानचित्र का नक्शा केस क्लास के साथ

case class WordAndWeight(code: Map[String, Map[String, Integer]])

यह मुझे निम्न त्रुटि देता है:

+-------+----------+
|     12|        13|
+-------+----------+
|[1,2,3]|[10,12,15]|
+-------+----------+


cannot resolve '`code`' given input columns: [12, 13];
org.apache.spark.sql.AnalysisException: cannot resolve '`code`' given input columns: [12, 13];
    at org.apache.spark.sql.catalyst.analysis.package$AnalysisErrorAt.failAnalysis(package.scala:42)
1
KeyMaker00 12 सितंबर 2018, 15:31
2
कितने उत्पादन की अपेक्षा है?
 – 
Ramesh Maharjan
12 सितंबर 2018, 16:10

1 उत्तर

सबसे बढ़िया उत्तर

आप स्कीमा को परिभाषित करने का प्रयास करते हैं जिसमें MapType रूट प्रकार के रूप में है। दूसरे शब्दों में आप चाहते हैं कि प्रत्येक पंक्ति मानचित्र हो। AFAIK स्पार्क MapType को रूट प्रकार के रूप में समर्थन नहीं करता है। यह रूट प्रकार के रूप में केवल स्ट्रक्चर टाइप का समर्थन करता है।

जब आप केस क्लास और प्रतिबिंब के माध्यम से इस तरह परिभाषित करते हैं:

val schema = ScalaReflection.schemaFor[KeywordData].dataType.asInstanceOf[StructType]

आपको स्ट्रक्चर टाइप रूट प्रकार के रूप में मिलता है:

root
  |-- keywordsByCode: map (nullable = true)
  |    |-- key: string
  |    |-- value: struct (valueContainsNull = true)
  |    |    |-- word: string (nullable = true)
  |    |    |-- weight: integer (nullable = true)

इसका मतलब है कि स्पार्क एक कॉलम के साथ डेटाफ्रेम बनाएगा जिसे keywordsByCode कहा जाता है। और यह इस तरह JSON की अपेक्षा करेगा

{"keywordsByCode":{"12":{"wordA":1,"wordB":2,"wordC":3},"13":{"wordX":10,"wordY":12,"wordZ":15}}}

आपको JSON को संशोधित करने या टेक्स्ट की तरह अपनी फ़ाइल पढ़ने की आवश्यकता है और फिर प्रत्येक पंक्ति को JSON में पार्स करना होगा।

अपडेट करें

मैंने एक और गलती नहीं देखी है, आप केस क्लास को इस तरह दिखना चाहिए:

case class KeywordData (keywordsByCode: Map[String, Map[String, Int]])

क्योंकि आपके JSON ने MapType को नेस्ट किया है। तो स्कीमा इस तरह दिखेगा:

root
|-- keywordsByCode: map (nullable = true)
|    |-- key: string
|    |-- value: map (valueContainsNull = true)
|    |    |-- key: string
|    |    |-- value: integer (valueContainsNull = true)

मेरा परीक्षण कोड:

val df = spark.read
  .option("multiline",true)
  .option("mode", "PERMISSIVE")
  .schema(ScalaReflection.schemaFor[KeywordData].dataType.asInstanceOf[StructType])
  .json("test.json")
 df.printSchema()
 df.explain(true)
 df.show(10)
1
Avseiytsev Dmitriy 12 सितंबर 2018, 16:50