dplyr:: 如果 uid 不存在则追加到 postgresql 远程源

dplyr:: append to postgresql remote source if uid not present

除非我遗漏了什么,否则文档中没有提及如何在实践中使用 db_write_table 等函数。包文档中的唯一参考是。

db_write_table(con, table, types, values, temporary = FALSE, ...)

types就不解释了。 dplyr 的 None 远程连接功能似乎在任何地方都有详细记录,例如dplyr.tidyverse.org.

我有一个数据库 mydb table mydata 我可以连接

require(RPostgreSQL)
require(dplyr)

drv <- dbDriver("PostgreSQL")
sapply(dbListConnections(drv), dbDisconnect)
con <- dbConnect(drv, dbname = "mydb", host = "localhost", port = 5432, user = "username")
data_db = tbl(con, 'mydata')

远程数据表 data_db 包含一个名为 uid 的字段。我有一个 data_frame dat 和我需要附加到 mydata 的观察结果,如果它们的 dat$uid 值不存在的话。

这可以用 db_write_table 完成还是需要 SQL 方法?

根据@hadley 对此 answer 的评论,您可以使用 dbWriteTable(append = TRUE)。这是 SQLite 的示例:

library(dplyr)

# Create some example data
con <- DBI::dbConnect(RSQLite::SQLite(), path = ":dbname:")
dd <- data.frame(uid = 1:20, value = LETTERS[1:20])
dat <- data.frame(uid = 15:26, value = LETTERS[15:26])
copy_to(con, dd, "my_data",
  temporary = FALSE, 
  indexes = list("uid", "value")
)

# Identify rows to append
dd_db <- tbl(con, "my_data")
dd_uid <- select(dd_db, uid) %>%
  collect() %>%
  unlist()
dat_to_append <- filter(dat, !(uid %in% dd_uid))

DBI::dbWriteTable(con, "my_data", dat_to_append, append = TRUE)

所以这是我的实现的价值,它应该对我的情况有更好的表现(大数据库的小附加):

db_add_unmatched = function(con, remote, dat, uid, append = TRUE, row.names = FALSE){
  tbl_remote = tbl(con, remote)
  dat_matched = select(tbl_remote, uid) %>% filter(uid %in% dat[[uid]]) %>% collect
  if(nrow(dat_matched) == 0){
    dat_unmatched = dat
  } else dat_unmatched = anti_join(dat, dat_matched, by = uid)
  if(nrow(dat_unmatched) > 0){
    DBI::dbWriteTable(con, remote, dat_unmatched, append = append, row.names = row.names)
  } else message('No unmatched rows to add')
}

db_add_unmatched(con, 'mydata', dat, 'uid')