我目前正在一个个人项目上,制作一个闪亮的仪表板,以跟踪每月的财务状况(收入,支出,储蓄等)并将其可视化。这个项目也是我学习如何应用SQL的工具,因此我正在使用RSQLite来管理数据库。
当前,我正在考虑闪亮的应用程序如何与SQL数据库交互。我想到了几种解决方案:
1)在会话开始时,该应用程序将数据库整体复制到一个反应变量中,该变量将继续进行计算并生成图。如果数据库很大,这可能会占用大量内存。 这是一个最小的工作示例
## creating example database
require("RSQLite")
require("shiny")
require("ggplot2")
require("reshape2")
db <- dbConnect(RSQLite::SQLite(), "")
dbSendQuery(conn = db,
"CREATE TABLE db
(month TEXT,
income REAL,
expense REAL,
savings REAL)")
dbSendQuery(conn = db,
"INSERT INTO db VALUES
('September',
4000,
2800,
1200)")
dbSendQuery(conn = db,
"INSERT INTO db VALUES
('October',
4000,
3000,
1000)")
## copy db into reactive
if (interactive()) {
options(device.ask.default = FALSE)
app <- shinyApp(
ui = fluidPage(
textOutput("avg.spend"),
textOutput("avg.save"),
plotOutput("plot")
),
server = function(input, output) {
df <- reactiveValues(x = dbGetQuery(conn = db, 'SELECT * FROM db'))
output$avg.spend <- renderText({
expense <- paste0("Average expenses: $", mean(df$x$expense))
print(expense)
})
output$avg.save <- renderText({
savings <- paste0("Average savings: $", mean(df$x$savings))
print(savings)
})
output$plot <- renderPlot({
df.melt <- melt(df$x, id = "month")
p <- ggplot(df.melt, aes(month)) + geom_bar(aes(weight = value, fill = variable), position = "identity")
plot(p)
})
}
)
runApp(app)
}
2)每当需要进行计算或需要生成图时,应用程序都会查询SQL数据库以获取所需的条目。但是,这可能意味着多个重复查询。 此处的示例(仅显示闪亮的应用程序部分以避免重复):
app <- shinyApp(
ui = fluidPage(
textOutput("avg.spend"),
textOutput("avg.save"),
plotOutput("plot")
),
server = function(input, output) {
output$avg.spend <- renderText({
qe <- dbGetQuery(conn = db, 'SELECT expense FROM db')
expense <- paste0("Average expenses: $", mean(qe$expense))
print(expense)
})
output$avg.save <- renderText({
qs <- dbGetQuery(conn = db, 'SELECT savings FROM db')
savings <- paste0("Average savings: $", mean(qs$savings))
print(savings)
})
output$plot <- renderPlot({
df <- dbGetQuery(conn = db, 'SELECT * FROM db')
df.melt <- melt(df, id = "month")
p <- ggplot(df.melt, aes(month)) + geom_bar(aes(weight = value, fill = variable), position = "identity")
plot(p)
})
}
)
哪个解决方案更优雅,资源占用更少?另外,在比较这两种解决方案时,我可能会错过一些事情吗?预先感谢!
编辑:添加了示例代码。想改一下我的问题:
1)一次将数据库存储为一个反应变量
或
2)仅在功能需要时(但多次)提取相关数据