Python 迭代pyspark数据帧,然后针对每一行与mongoDB交互
我有一个pyspark数据帧,现在我想迭代每一行并插入/更新mongoDB集合Python 迭代pyspark数据帧,然后针对每一行与mongoDB交互,python,mongodb,apache-spark,pyspark,pymongo-3.x,Python,Mongodb,Apache Spark,Pyspark,Pymongo 3.x,我有一个pyspark数据帧,现在我想迭代每一行并插入/更新mongoDB集合 #Did every required imports #dataframe +---+----+ |age|name| +---+----+ | 30| c| | 5| e| | 6| f| +---+----+ db = mongodbclient['mydatabase'] collection = db['mycollection'] #created belo
#Did every required imports
#dataframe
+---+----+
|age|name|
+---+----+
| 30| c|
| 5| e|
| 6| f|
+---+----+
db = mongodbclient['mydatabase']
collection = db['mycollection']
#created below function to insert/update
def customFunction(row):
key = {'name':row.name}
data = dict(zip(columns,[row.x for x in columns]))
collection.update(key, data, {upsert:true})
#return a_flag #commented it as of now, a_flag can be 0 or 1
如果mongoDB集合“mycollection”中存在名称,则应更新该行/记录,否则应插入该新记录
尝试将此函数映射到spark数据帧时出现以下错误
result = my_dataframe.rdd.map(customFunction)
#.....TypeError: can't pickle _thread.lock objects....
#AttributeError: 'TypeError' object has no attribute 'message'
请任何人找出“该功能和/或其他任何地方有什么问题”,或建议是否有其他替代方案
基本上迭代每一行(没有对方付费的调用,这是可能的吗??)
并且,在每一行上应用一个函数以在spark work之外运行
请建议,提前谢谢……)
我在mongoDB中的数据
name age
a 1
b 2
c 3 #new update should make age as 30 and 2 more new recs should inserted
看起来连接对象无法被pickle。我会使用
foreachPartition
:
def customFunction(rows):
db = mongodbclient['mydatabase']
collection = db['mycollection']
for row in rows:
key = {'name':row.name}
data = dict(zip(columns,[row.x for x in columns]))
collection.update(key, data, {upsert:true})
my_dataframe.rdd.foreachPartition(customFunction)
但是请记住,致命的故障可能会使数据库处于不一致的状态。如果在MongoDB中有500k条记录需要升级,则批量模式可能是更有效的处理方法。在mongoDB中执行请求将需要比在spark中实际执行的更多的功能(仅创建请求),即使并行执行,也可能导致mongo端的不稳定性(并且比“迭代”方法慢) 您可以尝试以下代码。它不使用
collect()
,因此在驱动程序上具有内存效率:
bulk = collection.initialize_unordered_bulk_op()
for row in rdd.toLocalIterator():
key = {'name':row.name}
data = dict(zip(columns,[row.x for x in columns]))
bulk.update(key, data, {upsert:true})
print(bulk.execute())
数据集有多大?导出是否需要并行运行?因为根据需要更新的记录数量,至少有3种有效的方法来实现您的需求。@Mariusz:mongoDB中的Base_集合有大约1.5亿条记录,spark dataframe的增量数据不超过500000条记录。请告诉我可用的选项。@Mariusz:我通常不喜欢收集或转换成pandas数据帧,然后再向上插入MongoDB。@Satya那么如何插入批量rdd?@ShaikRizwana:我的代码在遵循user8371915的答案后工作(连接对象不能被pickle,在Customfunction中创建conn对象). 这种方法比Mariusz的方法快(我仍然不明白为什么!!!)。实际上,我已经将我的存储从Mongo更改为HDFS,并且每次都对整个数据集进行聚合,并更新完整的结果集(是的,很奇怪,但我有其他依赖项,所以我不得不更改。)