[英]iterate over pyspark Dataframe and then for each row interact with mongoDB
我有一個pyspark數據框,現在我想遍歷每行並插入/更新到mongoDB集合。
#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-dataframe上映射此功能時出現以下錯誤
result = my_dataframe.rdd.map(customFunction)
#.....TypeError: can't pickle _thread.lock objects....
#AttributeError: 'TypeError' object has no attribute 'message'
任何人都可以找出“該功能和/或其他任何地方在哪里出問題了”,或者請提出是否有其他替代方法來解決此類任務。
基本上迭代每行(甚至沒有可能進行collect調用嗎?)
並且,在每一行上應用一個功能來運行外部火花工作。
請建議,在此先謝謝.. :)
我在mongoDB中的數據
name age
a 1
b 2
c 3 #new update should make age as 30 and 2 more new recs should inserted
似乎無法腌制連接對象。 我會用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中上傳50萬條記錄,則批量模式可能是處理此問題的更有效方法。 與您在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())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.