5

我有以下用 R 编写的函数(我认为)在更新我的 mongo 数据库集合方面做得很差。

library(mongolite) 

con <- mongolite::mongo(collection = "mongo_collection_1", db = 'mydb', url = 'myurl')
myRdataframe1 <- con$find(query = '{}', fields = '{}')
rm(con)

con <- mongolite::mongo(collection = "mongo_collection_2", db = 'mydb', url = 'myurl')
myRdataframe2 <- con$find(query = '{}', fields = '{}')
rm(con)

... code to update my dataframes (rbind additional rows onto each of them) ...

# write dataframes to database
write.dfs.to.mongodb.collections <- function() {

  collections <- c("mongo_collection_1", "mongo_collection_2") 
  my.dataframes <- c("myRdataframe1", "myRdataframe2")

  # loop dataframes, write colllections
  for(i in 1:length(collections)) {

    # connect and add data to this table
    con <- mongo(collection = collections[i], db = 'mydb', url = 'myurl')
    con$remove('{}')
    con$insert(get(my.dataframes[i]))
    con$count()

    rm(con)
  }
}
write.dfs.to.mongodb.collections()

我的数据框是非常大的数据框,目前约 100K 行和约 50 列myRdataframe1myRdataframe2每次我的脚本运行时,它:

  • 使用 con$find('{}') 将 mongodb 集合拉入 R,保存为数据框myRdataframe1
  • 从作为新行附加到的数据提供程序中抓取新数据myRdataframe1
  • 使用 con$remove() 和 con$insert 将mongodb 集合中的数据完全删除,然后重新插入整个myRdataframe1

最后一个要点是不确定的,因为我每天在 cronjob 中运行这个 R 脚本,而且每次我完全擦除 mongo db 集合并将 R 数据帧重新插入集合时,我都不喜欢这样。

如果我删除 con$remove() 行,我会收到一条错误消息,指出我有重复的 _id 键。看来我不能简单地使用 con$insert() 追加。

非常感谢您对此的任何想法!

4

2 回答 2

2

当您尝试根据主键将文档插入数据库中已经存在的 MongoDB 中时,您将获得重复键异常。为了解决这个问题,您可以_id在之前使用类似这样的内容简单地取消设置列con$insert

my.dataframes[i]$_id <- NULL

这样,新插入的文档将自动获得新的_id分配。

于 2018-10-15T19:46:56.327 回答
0

您可以使用 upsert (如果找到与第一个条件匹配的文档,它将更新它,如果不是,它将插入一个新的,首先您需要将 id 与每个文档分开

 _id= my.dataframes[i]$_id
 updateData = my.dataframes[i]
 updateData$_id <- NULL

然后使用upsert(可能有一些更简单的方法可以在 R 中连接字符串)

 con$update(paste('{"_id":"', _id, '"}' ,sep="" ) , paste('{"$set":', updateData,'}', sep=""), upsert = TRUE)
于 2018-10-21T21:32:19.013 回答