【问题标题】:Inserting arrays in Elasticsearch via PySpark通过 PySpark 在 Elasticsearch 中插入数组
【发布时间】:2017-02-11 00:50:52
【问题描述】:

我有一个很像这样的案例:

示例数据框:

from pyspark.sql.types import *
schema = StructType([  # schema
    StructField("id", StringType(), True),
    StructField("email", ArrayType(StringType()), True)])
df = spark.createDataFrame([{"id": "id1"},
                            {"id": "id2", "email": None},
                            {"id": "id3","email": ["email1@gmail.com"]},
                            {"id": "id4", "email": ["email1@gmail.com", "email2@gmail.com"]}],
                           schema=schema)
df.show(truncate=False)
+---+------------------------------------+
|id |email                               |
+---+------------------------------------+
|id1|null                                |
|id2|null                                |
|id3|[email1@gmail.com]                  |
|id4|[email1@gmail.com, email2@gmail.com]|
+---+------------------------------------+

我想把这个数据插入到Elasticsearch中,所以据我研究,我必须转换成索引格式:

def parseTest(r):
    if r['email'] is None:
        return r['id'],{"id":r['id']}
    else:
        return r['id'],{"id":r['id'],"email":r['email']}
df2 = df.rdd.map(lambda row: parseTest(row))
df2.top(4)
[('id4', {'email': ['email1@gmail.com', 'email2@gmail.com'], 'id': 'id4'}),
 ('id3', {'email': ['email1@gmail.com'], 'id': 'id3'}),
 ('id2', {'id': 'id2'}),
 ('id1', {'id': 'id1'})]

然后我尝试插入:

es_conf = {"es.nodes" : "node1.com,node2.com",
           "es.resource": "index/type"}
df2.saveAsNewAPIHadoopFile(
    path='-', 
    outputFormatClass="org.elasticsearch.hadoop.mr.EsOutputFormat",
    keyClass="org.apache.hadoop.io.NullWritable",
    valueClass="org.elasticsearch.hadoop.mr.LinkedMapWritable", 
    conf=es_conf)

我明白了:

org.apache.spark.SparkException:java.util.ArrayList 类型的数据 无法使用

Spark v 2.1.0
ES v 2.4.4

没有email 字段它工作正常,我找到了一些使用es.output.json: truejson.dumps 的建议解决方案,但它似乎适用于版本5,所以我尝试在另一个集群中使用ES v5

df3 = df2.map(json.dumps)
df3.top(4)
['["id4", {"email": ["email1@gmail.com", "email2@gmail.com"], "id": "id4"}]',
 '["id3", {"email": ["email1@gmail.com"], "id": "id3"}]',
 '["id2", {"id": "id2"}]',
 '["id1", {"id": "id1"}]']
es_conf2 = {"es.nodes" : "anothernode1.com,anothernode2.com",
           "es.output.json": "true",
           "es.resource": "index/type"}
df3.saveAsNewAPIHadoopFile(
    path='-', 
    outputFormatClass="org.elasticsearch.hadoop.mr.EsOutputFormat",
    keyClass="org.apache.hadoop.io.NullWritable",
    valueClass="org.elasticsearch.hadoop.mr.LinkedMapWritable", 
    conf=es_conf2)

然后我得到:

不能使用 java.lang.String 类型的 RDD 元素

Spark v 2.1.0
ES v 5.2.0

感觉很糟糕

【问题讨论】:

    标签: apache-spark elasticsearch pyspark elasticsearch-hadoop


    【解决方案1】:

    我找到了另一种方法来完成相同的工作,即使用数据框对象的 write 方法。

    所以,在第一部分之后:

    from pyspark.sql.types import *
    schema = StructType([  # schema
        StructField("id", StringType(), True),
        StructField("email", ArrayType(StringType()), True)])
    df = spark.createDataFrame([{"id": "id1"},
                                {"id": "id2", "email": None},
                                {"id": "id3","email": ["email1@gmail.com"]},
                                {"id": "id4", "email": ["email1@gmail.com", "email2@gmail.com"]}],
                               schema=schema)
    df.show(truncate=False)
    +---+------------------------------------+
    |id |email                               |
    +---+------------------------------------+
    |id1|null                                |
    |id2|null                                |
    |id3|[email1@gmail.com]                  |
    |id4|[email1@gmail.com, email2@gmail.com]|
    +---+------------------------------------+
    

    你只需要:

    df.write\
        .format("org.elasticsearch.spark.sql")\
        .option("es.nodes","node1.com,node2.com")\
        .option("es.resource","index/type")\
        .option("es.mapping.id", "id")\
        .save()
    

    无需转化为RDD或以任何方式修改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 2020-08-27
      • 2015-02-20
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多