如何有效地从mongodb读取数据并将其转换为spark的数据帧?

时间:2016-04-20 10:26:54

标签: mongodb pyspark spark-dataframe

我已经研究了很多,但找不到解决方案。我能找到的最近的问题是Why my SPARK works very slowly with mongoDB

我正在尝试使用mongo-hadoop连接器将mongodb集合加载到spark的DataFrame中。以下是相关代码的片段:

connection_string = 'mongodb://%s:%s/randdb.%s'%(dbhost, dbport, collection_name)
trainrdd = sc.mongoRDD(connection_string, config=config)
#     traindf = sqlcontext.createDataFrame(trainrdd)
#     traindf = sqlcontext.read.json(trainrdd)
traindf = sqlcontext.jsonRDD(trainrdd) 

这里,'sc'是SparkContext对象。我也尝试过在代码中注释掉的变体。但所有人都同样缓慢。对于大小为2GB(100000行和1000列)的集合,在3台机器的集群上需要大约6小时(圣莫利:/),每台机器具有12个核心和72 GB RAM(使用此火花簇中的所有核心)。 Mongodb服务器也在其中一台机器上运行。

我不确定我是否正确地做到了。有关如何优化此代码的任何指示都非常有用。

2 个答案:

答案 0 :(得分:2)

默认情况下,pyspark.sql.SQLContext.jsonRDD将动态推断给定JSON数据集的架构。在找到新的JSON字段时将添加列。这可能会很慢,因为每个JSON属性都会被检查。特别是如果你有1000个coloumns。

您可以做的是明确定义架构,如果数据已知,则只需要一组特定的字段。

此外,由于HADOOP-277中描述的ObjectId问题,您需要删除包含此类不兼容类型的字段,或转换为其他类型。即str(ObjectId(...))

例如:

from pyspark import SparkContext, SparkConf
from pyspark.sql import SQLContext
from pyspark.sql.types import StructType, StructField, StringType
import pymongo_spark 
pymongo_spark.activate()
data_rdd = sc.mongoRDD("mongodb://localhost:27017/database.collection")
sqlcontext = SQLContext(sc)

# Define your schema explicitly
schema = StructType([StructField("firstname", StringType()),
                     StructField("lastname", StringType()),
                     StructField("description", StringType())])

# Create a mapper function to return only the fields wanted, or to convert. 
def project(doc):
    return {"firstname": str(doc["firstname"]), 
            "lastname": str(doc["lastname"]), 
            "description": str(doc["description"])}

projected_rdd = data_rdd.map(project)
train_df = sqlcontext.jsonRDD(projected_rdd, schema)
train_df.first()

以上代码段在环境中进行了测试:Spark v1.6.1,mongo-hadoop spark v1.5.2

答案 1 :(得分:2)

使用pyspark从mongo读取数据的有效方法是使用MongoDb spark connector

from pyspark.sql import SparkSession, SQLContext
from pyspark import SparkConf, SparkContext
sc = SparkContext()
spark = SparkSession(sc)
data = spark.read.format("com.mongodb.spark.sql.DefaultSource").option("spark.mongodb.input.uri","mongodb://+username:password@server_details:27017/db_name.collection_name?authSource=admin").load()

这将是spark数据帧,无需对其进行转换。您只需要配置mongodb spark连接器。

如果您使用的是笔记本,请在顶部写上这个

 %%configure
{"conf": {"spark.jars.packages": "org.mongodb.spark:mongo-spark-connector_2.11:2.3.2"}}

如果您使用的是spark-submit命令:

spark-submit --conf spark.pyspark.python=/usr/bin/anaconda/envs/py35/bin/python3.5 --packages org.mongodb.spark:mongo-spark-connector_2.11:2.3.1 file_name.py