我正在尝试使用各种数据框中的R将很多数据(数百万个文档)插入到mongodb中,我将在不同的时间获取这些数据。
每个数据框将具有相同的主ID,但可以具有相同或不同的属性。
如果记录存在,我想添加任何新属性并附加任何现有属性。如果记录不存在,我想创建它。
这对R有效吗?我试图使用美妙的mongolite包,但插入选项因为存在重复记录而失败。
任何指针都非常感激。
由于
伊恩
id<-LETTERS[1:5]
value1<-paste0("value1_",letters[1:5])
value2<-paste0("value2_",letters[1:5])
value3<-paste0("additional_value_1",letters[1:5])
df1<-as.data.frame(cbind(id,value1))
df2<-as.data.frame(cbind(id,value2))
df3<-as.data.frame(cbind(id,value3))
colnames(df1)<-c('_id','value1')
colnames(df2)<-c('_id','value2')
colnames(df3)<-c('_id','value1')
desired_value1<-paste0( "[",paste(paste0("'",value1,"'"),paste0("'",value3,"'"),sep=","),"]")
df4<-cbind(id,desired_value1,value2)
df4<-as.data.frame(cbind(id,desired_value1,value2))
colnames(df4)<-c("_id","value1","value2")
答案 0 :(得分:1)
此答案使用library(rmongodb)
,不再支持Cran。
这个答案在一定程度上取决于你如何获得'新'数据框架。我也无法在不知道您的设置和数据大小的情况下回答高效部分,但希望这可以帮助您入门。另外,我发现从R中插入/撤回数百万条记录到mongo中的速度非常慢。
执行此操作的一种方法是为您获得的每个新data.frame
,将匹配的记录带回R并“加入/更新”它们,然后仅为这些文档更新数据库,同时附加新数据使用update / upsert
查询。
我的大多数r-mongodb作品也使用library(rmongodb)
略微修改您的数据以使用id
代替_id
:
id<-LETTERS[1:5]
value1<-paste0("value1_",letters[1:5])
value2<-paste0("value2_",letters[1:5])
value3<-paste0("additional_value_1",letters[1:5])
df1<-as.data.frame(cbind(id,value1), stringsAsFactors = F) ## removed factor levels
df2<-as.data.frame(cbind(id,value2), stringsAsFactors = F)
df3<-as.data.frame(cbind(id,value3), stringsAsFactors = F)
colnames(df1)<-c('id','value1')
colnames(df2)<-c('id','value2')
colnames(df3)<-c('id','value1')
desired_value1<-paste0( "[",paste(paste0("'",value1,"'"),paste0("'",value3,"'"),sep=","),"]")
df4<-cbind(id,desired_value1,value2)
df4<-as.data.frame(cbind(id,desired_value1,value2))
colnames(df4)<-c("_id","value1","value2")
第一步是将其插入数据库
library(rmongodb) ## my preferred r mongodb package
library(jsonlite) ## for viewing/checking results
library(data.table) ## for fast rbind & data frame manipulation
mongo <- mongo.create()
mongo.is.connected(mongo)
# [1] TRUE
db <- "test"
coll <- "test"
bs <- mongo.bson.from.df(df1)
ns <- paste0(db, ".", coll)
## insert.batch - insert each 'row' of the df as a document
mongo.insert.batch(mongo = mongo,
ns = ns,
lst = bs)
# [1] TRUE
检索所有文件以检查上传
f <- mongo.bson.from.list(list("_id" = 0)) ## to ignore the _id field
res <- mongo.find.all(mongo = mongo, ns = ns, fields = f)
toJSON(res, pretty=T)
# [
# {
# "id": ["A"],
# "value1": ["value1_a"]
# },
# {
# "id": ["B"],
# "value1": ["value1_b"]
# },
# {
# "id": ["C"],
# "value1": ["value1_c"]
# },
# {
# "id": ["D"],
# "value1": ["value1_d"]
# },
# {
# "id": ["E"],
# "value1": ["value1_e"]
# }
# ]
现在,如果我们想将df2$value2
添加到这些文档中,我们可以将它们带回R来操作它们,然后更新数据库
qry <- list("id" = list("$in" = df2$id))
## mongo shell query: db.test.find({"id" : { "$in" : ["A", "B", ..., ]}})
qry <- mongo.bson.from.list(qry)
f <- list("_id" = 0)
res <- mongo.find.all(mongo = mongo,
ns = ns,
query = qry,
fields = f)
dt_res <- rbindlist(res)
## set our df2 to data.table, and join onto dt_res
setDT(df2)
## add a new row to df2, with a new id, to check the update.upsert works
df2 <- rbindlist(list(df2, data.table(id = "Z", value2 = "value2_z")))
dt_res <- dt_res[ df2, on="id"] ## left join to keep our 'z' row
dt_res
# id value1 value2
# 1: A value1_a value2_a
# 2: B value1_b value2_b
# 3: C value1_c value2_c
# 4: D value1_d value2_d
# 5: E value1_e value2_e
# 6: Z NA value2_z
我们现在可以使用udpate
and upsert
for(i in 1:nrow(dt_res)){
crit <- mongo.bson.from.list(list("id" = dt_res[i, id]))
d <- c(dt_res[i, ])
mongo.update(mongo = mongo,
ns = ns,
criteria = crit,
objNew = d,
flags = c(mongo.update.upsert))
}
通过返回所有内容来检查documnet是否已被更新
f <- mongo.bson.from.list(list("_id" = 0)) ## to ignore the _id field
res <- mongo.find.all(mongo = mongo, ns = ns, fields = f)
toJSON(res, pretty=T)
# [
# {
# "id": ["A"],
# "value1": ["value1_a"],
# "value2": ["value2_a"]
# },
# {
# "id": ["B"],
# "value1": ["value1_b"],
# "value2": ["value2_b"]
# },
# {
# "id": ["C"],
# "value1": ["value1_c"],
# "value2": ["value2_c"]
# },
# {
# "id": ["D"],
# "value1": ["value1_d"],
# "value2": ["value2_d"]
# },
# {
# "id": ["E"],
# "value1": ["value1_e"],
# "value2": ["value2_e"]
# },
# {
# "id": ["Z"],
# "value1": {},
# "value2": ["value2_z"]
# }
# ]
请注意,这包括我们新的'z'id