我有一个pyspark Dataframe,现在我想迭代每一行并插入/更新到mongoDB集合。
c.Validation.Required("addr").Ok
如果mongoDB集合'mycollection'中存在名称,则应更新该行/记录,否则插入该新记录。
我试图通过spark-dataframe
映射此函数时出现以下错误 #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中的数据
result = my_dataframe.rdd.map(customFunction)
#.....TypeError: can't pickle _thread.lock objects....
#AttributeError: 'TypeError' object has no attribute 'message'
答案 0 :(得分:1)
看起来连接对象无法被腌制。我使用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)
但请记住,致命的失败可能会使数据库处于不一致状态。
答案 1 :(得分:1)
如果要在MongoDB中存储500k记录,则批量模式可能是处理此问题的更有效方法。与你在spark中实际执行的操作(仅创建请求)相比,执行mongoDB中的请求需要更多的功能,甚至并行执行此操作可能会导致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())