使用Rs mongolite正确(插入?更新?)将数据添加到现有集合中

时间:2018-10-05 21:08:12

标签: r mongodb mongolite

我有以下用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()

我的数据帧myRdataframe1myRdataframe2是非常大的数据帧,目前有约10万行和约50列。每次我的脚本运行时,它:

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

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

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

对此表示感谢!

2 个答案:

答案 0 :(得分:2)

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

my.dataframes[i]$_id <- NULL

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

答案 1 :(得分: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)