Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 迭代pyspark数据帧,然后针对每一行与mongoDB交互_Python_Mongodb_Apache Spark_Pyspark_Pymongo 3.x - Fatal编程技术网

Python 迭代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

我有一个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数据帧时出现以下错误

 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,并且每次都对整个数据集进行聚合,并更新完整的结果集(是的,很奇怪,但我有其他依赖项,所以我不得不更改。)