R Ошибка блестящей реактивной среды при создании приложений с использованием графических данных Neo4j - PullRequest
2 голосов
/ 12 марта 2019

Я создаю интерактивное приложение Shiny, используя данные графика Neo4j, используя пакет RNeo4j для соединения Neo4j с R.

Приложение содержит таблицу, отображающую свойства графических данных, извлеченных из Neo4j, пользователи могут просматривать и изменять содержимое таблицы (свойства графических данных). Изменения могут быть записаны обратно в Neo4j как обновление свойств данных графа. Эта функция может быть выполнена с использованием updateProp & getOrCreateNode functiona в пакете RNeo4j.

Однако у меня возникла реактивная ошибка.

Ниже мой код:

library(RNeo4j)
library(dplyr)
library(shiny)
library(shinydashboard)
library(visNetwork)
library(tidyr)
library(sqldf)
library(igraph)
library(plotly)
library(stringi)
library(stringr)

graph = startGraph("http://localhost:7474/db/data/", username = "xxx", password = "xxx")
summary(graph)

# build dashboard
# UI items list 
header <- dashboardHeader(
  title = "Neo4j"
)

sidebar <- dashboardSidebar(
  sidebarMenu (
  )
)

body <- dashboardBody(
  tabItems(
    tabItem(tabName = "dashboard1",
            box(textOutput("aa")),
            box(title = "CATEGORY", DT::dataTableOutput("category")),
            box(uiOutput("category_status"))

    )
  )
)

# UI
ui <- dashboardPage(header, sidebar, body)

# Server
server <- function(input, output, session) {

  # Query graph data and properties from Neo4j and store them in table format in R 
  query = "
  MATCH (c:Category)
  RETURN c.id AS Category, c.Price AS Price, c.status AS Category_Status
  "
  info = cypher(graph, query) # R Table to store Neo4j data

  # Build Shiny output tables
  output$i1 <- renderTable(info)
  output$category = DT::renderDataTable(info, selection = 'single')
  # This is to build the function of change the status of category with 3 options
  output$category_status = renderUI({
    x = info[input$category_rows_selected, ]
    if (length(x)){
      selectInput("category_status", "", 
                  c( "Sold", "On Sale","Out of Stock"), 
                  selected = x$Category_Status)
    }
  })
  # Table to examine if the status change was made successfully
  output$aa<-renderText(input$category_status)

  # Write back the changes made in Shiny to Neo4j using "updateProp" & "getOrCreateNode" function in RNeo4j
  if(info$Category_Status[input$category_rows_selected] != input$category_status) {
    category_num = as.numeric(substring(info$Category[input$category_rows_selected], 16))
    updateProp(getOrCreateNode(graph, "Category", Category = paste("CC_CCAA_AAC.0C-", category_num, sep="")), 
               status = input$status)
  }
}

# Shiny dashboard
shiny::shinyApp(ui, server)

Ниже приведено сообщение об ошибке:

Listening on http://127.0.0.1:4401
Warning: 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.)
  55: stop
  54: .getReactiveEnvironment()$currentContext
  53: .subset2(x, "impl")$get
  52: $.reactivevalues
  50: server [#44]
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.)

По следам и ошибкам приложение Shiny может работать должным образом, если я удалю код написанных изменений обратно в Neo4j, который является последней частью кода. Тем не менее, это основная функция этого проекта.

Кроме того, эта функция обратной записи работала должным образом, стоя в стороне от Shiny. Таким образом, проблема заключается во взаимодействии между двумя частями.

Мне интересно, могу ли я добавить observeEvent в Shiny для решения этой проблемы.

Заранее спасибо.

1 Ответ

1 голос
/ 12 марта 2019

Как вы сказали, последняя часть вашего кода вызвала проблему.Причина в том, что вы используете reactives в этом фрагменте кода.То есть вы используете input$category_rows_selected, input$category_status и input$status, которые не имеют фиксированного значения, но зависят от вашего взаимодействия с приложением.

В зависимости от того, что вы хотите сделать, у вас есть в основном 2 варианта:

  1. Включить фрагмент кода в isolate.Однако в этом случае ваш код никогда не будет обновляться при изменении соответствующих входных данных.
  2. Включите фрагмент кода в observe.В этом случае всякий раз, когда какой-либо из входов (как указано выше) меняет свое значение, этот код будет выполняться.Если вы хотите, чтобы блок кода выполнялся только в случае изменения некоторых входов, вы можете isolate вводить данные, от которых вы не хотите зависеть.

Например, этот код будет выполняться всякий раз, когда input$category_rows_selected или input$category_status изменяется, но не меняется, если input$status изменяется, поскольку он заключен в isolate:

observe({
   if(info$Category_Status[input$category_rows_selected] != input$category_status) {
       category_num = as.numeric(substring(info$Category[input$category_rows_selected], 16))
       updateProp(getOrCreateNode(graph, "Category", 
                  Category = paste("CC_CCAA_AAC.0C-", category_num, sep="")), 
                  status = isolate(input$status))
  }
})
...