如何在实时数据框中保存 sql 数据库?闪亮的

Posted

技术标签:

【中文标题】如何在实时数据框中保存 sql 数据库?闪亮的【英文标题】:how to save a sql database in a real time dataframe? shiny 【发布时间】:2020-09-17 17:44:48 【问题描述】:

1.问题: 我正在使用一个 sql 数据库,该数据库由我的闪亮应用程序和另一个闪亮的应用程序更新。我使用df=isolate(reactivePoll ()) 能够对数据帧进行子集化,因为 reactivePoll 会生成 function 结果,但是isolate() 方法有一个严重的问题:它只在闪亮的应用程序打开时更新数据帧,它只运行一次。

如何实时更新数据框对象并能够对其进行子集化?没有错误:Error in: object of type 'closure' is not subsettableWarning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

例如,reactivepoll 函数在渲染函数中可以很好地实时显示表格,但是如何实时更新 data.frame?能够对其进行子集化 df$col1 df$col2 等?

server(input,output,session)
df=reactivePoll(intervalMillis = 2000,session, checkFunc = function()
   
    QUERY1= "SELECT *  FROM table"
       df_rs = dbSendQuery(storiesDb,QUERY1)
    dbFetch(df_rs), 
    valueFunc =function ()
     
      QUERY1= "SELECT *  FROM table"
    
      df_rs = dbSendQuery(storiesDb,QUERY1)
      dbFetch(df_rs)
      
      
       ) 
dataframe=  isolate(df()) # this approach makes the dataframe update only when the shiny app open.

尝试

1-我已经尝试使用dataframe=reactive(df ()),但是当我尝试对 dataframe$col1 进行子集设置时出现错误:Error in: object of type 'closure' is not subsettable

2-我已经尝试使用dataframe=df (),但报错:Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

【问题讨论】:

错误和您的代码表明您正在尝试错误地访问df()。它必须reactiveeventReactiveobserveobserveEventrender* 函数之一内。对于任何反应式表达式都是如此,而不仅仅是从 reactivePoll 返回的表达式。 例如,如果你这样做df2 <- reactive( head(df(), 1) ) 就可以正常工作(并不是说这是有意义的事情)。 感谢您的回答,我尝试了这个并给出了以下错误:警告:错误:“闭包”类型的对象不是子表 53:ifelse [# 267] 52:服务器 [# 267]错误:“闭包”类型的对象不是子集 “闭包”实际上是一个函数,所以你不小心做了reactive( head(df, 1) ) 不,我没有忘记() 【参考方案1】:

我认为您最好使用invalidateLater 而不是reactivePoll。后者旨在使用一个

相对便宜的“检查”功能和更昂贵的值检索功能

在您的情况下,无论如何,您打算每 2 秒运行一次查询。不需要“检查”。

此外,shiny 中的 reactive* 函数往往是 惰性的(如果没有任何依赖,它将永远不会触发),而 observe* 函数更贪婪(并且不管依赖项)。

这个怎么样?

dat <- reactiveValue(NULL)
observe(
  invalidateLater(2000)
  QUERY1 = "SELECT * FROM table"
  ret <- dbGetQuery(storiesDb, QUERY1)
  dat(ret)
)
output$tbl <- renderDataTable(
  dat()
)

您可能只想考虑下载最近数据,具体取决于该表的架构。例如,如果有一个时间戳(例如,Created 表示数据何时插入到表中),那么也许您可以使用类似

dat <- reactiveValue(NULL)
observeEvent(invalidateLater(2000), 
  olddat <- dat()
  latest <- max(c(as.POSIXct("1900-01-01"), olddat$Created), na.rm = TRUE)
  QUERY1 = "SELECT * FROM table t where t.Created > ?"
  newdat <- dbGetQuery(storiesDb, QUERY1, params = list(latest))
  if (NROW(newdat) > 0) 
    newdat <- rbind(olddat, newdat)
    dat(newdat)
  
)
output$tbl <- renderDataTable(
  dat()
)

根据您的架构,您的表中可能还有一个Modified 字段,其中Created 表示首次添加的时间,Modified 表示上次更改的时间。在这种情况下,您可能需要检查这两个字段的新近度。 (也许我现在超前了。)


然而,您可以使用reactivePoll 执行“快速”检查功能和“较慢”值功能,可能类似于:

df <- reactivePoll(2000, session,
  checkFunc = function() 
    dbGetQuery(storiesDb, "select count(*) as n from table")
  ,
  valueFunc = function() 
    dbGetQuery(storiesDb, "select * from table")
    
)
output$tbl <- renderDataTable(
  df()
)

这个想法(使用valueFunc 来计算行数)也可以适用于利用CreatedModified ...事实上,如果你有这些字段中的一个或两个,大多数表将是索引/优化,以便查询max(Created) 非常快。当然,获取表的行数通常会优化为近乎立即的查询,因此您可能会从一些内部基准测试和/或与 DBA 的讨论中受益。

【讨论】:

【参考方案2】:

reactivePoll 返回一个响应式对象,因此您只能在响应式上下文中访问它。如果要对其进行子集化,可以使用以下编码样式:

df_subset <- reactive(
  df()[, input$selected_col]
)

这再次返回一个反应对象,所以你可以显示它:

output$table <- renderTable(
  df_subset()
)

如果您想在df_subset 发生更改时对数据库进行更改,您可以使用observeEvent

observeEvent(subset_df(), 
  # code to change the DB
)

【讨论】:

以上是关于如何在实时数据框中保存 sql 数据库?闪亮的的主要内容,如果未能解决你的问题,请参考以下文章

mfc如何将复选框勾选后,把里面内容实时传到列表框中?

PHP如何接收动态数据保存并实时显示到网页上?

C#webfrom+sql2005如何实时判定用户在线

通过Pipelinedb使用SQL查询Kafka实时流数据

如何在 Amazon DynamoDB 中保存实时和历史车辆位置数据

如何实现EXCEL实时提取SQL中表的数据?