neo4j-rstats / neo4r Goto Github PK
View Code? Open in Web Editor NEWA Modern and Flexible Neo4J Driver
Home Page: https://neo4j-rstats.github.io/user-guide/
License: Other
A Modern and Flexible Neo4J Driver
Home Page: https://neo4j-rstats.github.io/user-guide/
License: Other
Trying to follow {neo4r} user guide chapter 6 (convert_to), and getting the following error messages:
Error in convert_to(., "igraph") : could not find function "convert_to"
Error in convert_to(., "visNetwork") : could not find function "convert_to"
Follwing code snippet only delivers a part of the actual graph schema:
library(neo4r)
con <- neo4j_api$new(url = "http://52.86.4.26:34781", user = "neo4j", password = "cheaters-garages-cardboard")
con$get_schema()
#> # A tibble: 1 x 2
#> label property_keys
#> <chr> <chr>
#> 1 Station sid
The Station
nodes contain at least one more property name
which is not shown in the schema? Why is it so? Is it also possible to see which relationship types exist?
For now the way the JSON api call is kind of a hack, there must be a way to code it a better way.
I need to write something that looks exactly like :
{
"statements" : [ {
"statement" : "CREATE (n) RETURN id(n)"
} ]
}
For now I'm doing :
to_json_neo <- function(query, include_stats, meta, type){
toJSON(list(statement = query, includeStats = include_stats, meta = meta, resultDataContents = list(type)), auto_unbox = TRUE)
}
query_jsonised <- to_json_neo(query_clean, include_stats, meta, type)
body <- glue('{"statements" : [ %query_jsonised% ]}', .open = "%", .close = "%")
Instead of using vec_to_cypher
, the idea would be able to pass a list and create a node from there. The benefit is that we can handle columns with NA's by dropping them and avoiding null property errors.
This feature existed within RNeo4j here.
While this ask is for the creation of a single node, the majority of my use-cases when using R is for bulk data creation, so bonus points for the ability to dump a dataframe to a list with one entry for each row, the "rows" option in jsonlite::toJSON
.
We should be able to select, open and send a CSV from the Connection Pane
I can build up the connection between Neo4j and R. However, I got an error message when I call the API. Below is an example of the error when I tried to run a Cypher query pulling data.
> library(neo4r)
> library(magrittr)
> con <- neo4j_api$new(url = "http://localhost:7474",
+ user = "xxx", password = "xxx")
>
> con$ping()
[1] 401
>
> 'MATCH (p:Person) -[r:ACTED_IN] -> (m:Movie) RETURN *;' %>%
+ call_neo4j(con, output = "json")
Error: API error
Thanks in advance.
The current bottleneck is the result parsing:
library(neo4r)
con <- neo4j_api$new(url = "http://138.197.15.1:7474", user = "all", password = "readonly")
con$ping()
"match (t:Tag) return t.name as name, size((t)--()) as deg limit 1000;" %>%
call_api(con)
# Calling the API take 500 ms
bench::mark({
res <- POST(url = glue("{con$url}/db/data/transaction/commit?includeStats=true"),
add_headers(.headers = c("Content-Type"="application/json",
"accept"="application/json",
#"X-Stream" = "true",
"Authorization"= paste0("Basic ", con$auth))),
body = body)
})
# A tibble: 1 x 14
expression min mean median max `itr/sec`
<chr> <bch> <bch> <bch:> <bch> <dbl>
1 {... 561ms 561ms 561ms 561ms 1.78
# while parsing the results around 2.5 seconds
bench::mark({
parse_api_results(res = res, type = type, format = format, include_stats = include_stats, meta = meta)
})
# A tibble: 1 x 14
expression min mean median max `itr/sec` mem_alloc
<chr> <bch> <bch> <bch:> <bch> <dbl> <bch:byt>
1 {... 2.29s 2.29s 2.29s 2.29s 0.437 10.1MB
I'm not sure db.schema is returned / parse at it should.
'call db.schema' %>%
call_api(con)
$nodes
# A tibble: 15 x 1
row
<list>
1 <list [0]>
2 <chr [1]>
3 <list [1]>
4 <list [0]>
5 <chr [1]>
6 <list [0]>
7 <list [0]>
8 <chr [1]>
9 <list [0]>
10 <list [0]>
11 <chr [1]>
12 <list [1]>
13 <list [0]>
14 <chr [1]>
15 <list [1]>
$relationships
# A tibble: 0 x 1
# ... with 1 variable: row <list>
'call db.schema' %>%
call_api(con, type = "graph")
$nodes
# A tibble: 5 x 3
id label properties
<chr> <list> <list>
1 -58 <chr [1]> <list [3]>
2 -60 <chr [1]> <list [3]>
3 -59 <chr [1]> <list [3]>
4 -57 <chr [1]> <list [3]>
5 -56 <chr [1]> <list [3]>
$relationships
# A tibble: 2 x 5
id type startNode endNode properties
<chr> <chr> <chr> <chr> <list>
1 -24 has_recorded -59 -60 <list [0]>
2 -23 MAINTAINS -58 -56 <list [0]>
unnest_graph
doesn't work here :
'call db.schema' %>%
call_api(con, type = "graph") %>%
unnest_graph()
Erreur : Columns `name`, `constraints` must be length 0, not 1, 1
Still R6 default right now
A customer tried to test the R-driver, but got the following error.
————————————
It seems like is getting a timeout. Do you have any input on what may be wrong?
timeouts with:
devtools::install_github("neo4j-rstats/neo4r”)
Another colleague tried to connect via a virtual machine and her response was:
“I tried now in VDI and I got also “ Installation failed: Timeout was reached: Connection timed out after 10000 milliseconds””
————————————
Differing number of rows error if the node has more than one label on it - e.g.:
l<-"MATCH (p:Person {name: 'Tom Hanks'}) SET p:Test return p" %>% call_neo4j(con, type = "row")
G <-"MATCH a=(p:Person {name: 'Tom Hanks'})-[r:ACTED_IN]->(m:Movie) RETURN a;" %>% call_neo4j(con, type = "graph") %>% convert_to('igraph')
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 14, 13
You can see that in unnest_nodes that the lab and df data frames have different lengths:
Hi,
I'm mainly using queries which output summaries, e.g. counts, averages etc. such as:
MATCH (u:User)
RETURN u.status as status, count(u) as n_users
which produce hard-to-use outputs, a list of data frames with one column called value
...
List of 2
$ status :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of 1 variable:
..$ value: int [1:5] 0 9 8 14 3
..- attr(*, ".internal.selfref")=<externalptr>
$ n_users:Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 5 obs. of 1 variable:
..$ value: int [1:5] 3819684 887574 16521 2367 58606
..- attr(*, ".internal.selfref")=<externalptr>
- attr(*, "class")= chr [1:3] "neo" "neo" "list"
You can always stitch them back together afterwards...
MATCH (u:User)
RETURN labels(u) as labels, count(u) as n_users
yields
Error in .x[[i]] : subscript out of bounds
(Because they add an extra layer, so removing the NULLs fails)
MATCH (u:User)
RETURN {labels:labels(u), n_users:count(u)}
But
meta
part with each row is not NULL in the neo4j response...format
argument and reshape the output as done in my code here (which still fails when one of the fields is a list...)Hope it helps
The include_stats
argument of the call_api
function is now FALSE by default.
It returns the stats about the actions performed by the call, e.g. :
# A tibble: 12 x 2
type value
<chr> <dbl>
1 contains_updates 1.
2 nodes_created 1021.
3 nodes_deleted 0.
4 properties_set 1021.
5 relationships_created 0.
6 relationship_deleted 0.
7 labels_added 1021.
8 labels_removed 0.
9 indexes_added 0.
10 indexes_removed 0.
11 constraints_added 0.
12 constraints_removed 0.
It would make sense that it is always returned when called on a CREATE / MERGE (just as above), but would it be less practical to have it to TRUE by default when we are querying data :
'MATCH (u:User) RETURN COUNT(u) AS Users_count' %>%
call_api(con, include_stats = TRUE)
$Users_count
# A tibble: 1 x 1
value
<int>
1 1021
$stats
# A tibble: 12 x 2
type value
<chr> <dbl>
1 contains_updates 0.
2 nodes_created 0.
3 nodes_deleted 0.
4 properties_set 0.
5 relationships_created 0.
6 relationship_deleted 0.
7 labels_added 0.
8 labels_removed 0.
9 indexes_added 0.
10 indexes_removed 0.
11 constraints_added 0.
12 constraints_removed 0.
I'm using the game of thrones dataset and ask back the relationships per book
MATCH ()-[r]->()
RETURN r.book as book, count(r) ORDER BY book
The browser returns a table
╒══════╤══════════╕
│"book"│"count(r)"│
╞══════╪══════════╡
│1 │684 │
├──────┼──────────┤
│2 │775 │
├──────┼──────────┤
│3 │1008 │
├──────┼──────────┤
│45 │1329 │
├──────┼──────────┤
│null │2823 │
└──────┴──────────┘
neo4r seems to ignore the null, but can't return a data frame either because of the unequal lengths, so it returns a list with a tibble of nrow 4 and a tibble with nrow 5
We can use all the tools available in R to build a global importer for tabular format.
How it would work:
LOAD CSV FROM {plumberapiurl}
cypher codeIf the user or password are false, the connection with neo4r::neo4j_api$new
should not work.
Add a test on con$ping() == 200
for instance, otherwise return an error.
Would hope that the call would recognize that there's no data and return a message indicating that the query returned no data. For example:
x<-"call apoc.meta.graph" %>% call_api(con, type = 'graph')
Your call can't be converted to a graph.
Please switch to type = "row".
switching to row will return nothing.
A significant part of the package can be tested without any interaction with the API (all the results parsing, and manipulation).
A neat idea of @RMHogervorst at ThinkR-open/isc-proposal#3
I'm wondering if the implementation of create_nodes
/ create_constraint
and such would make sense?
Here are why :
Do we really implement one node/relationship at a time at some point ? Given that the package will implement an as_nodes
from a dataframe, it seems to me that we are more prone to create a bulk of nodes than a single node
Is create_nodes("Person", name = "Colin", con_object)
significantly quicker/less verbose than call_api("CREATE (Person {name : 'Colin'})", con_object)
?
What's your take on that ?
Maybe putting it in a another package would make sens.
Not a bug, but as I am looking at the docs, README, and the guide, I think it might be easier if we all had a common dataset to work through as we "learn" the api of neo4r
.
It could be neat/easy to do something like neo4j_api$create_example_graph()
. I am sure the command could be more succinct, but you get the idea.
This might help with tests and debugging of issues.
Seems to be tied to relationships with properties. Have other examples of same type of error that seem to be the same root cause
res<-"MATCH (people:Person)-[relatedTo]-(:Movie {title: 'Cloud Atlas'}) RETURN people.name, Type(relatedTo), relatedTo" %>%
call_neo4j(con, type = 'row')
Should return
╒══════════════════╤═════════════════╤══════════════════════════════════════════════════════════════════════╕
│"people.name" │"type(relatedTo)"│"relatedTo" │
╞══════════════════╪═════════════════╪══════════════════════════════════════════════════════════════════════╡
│"Hugo Weaving" │"ACTED_IN" │{"roles":["Bill Smoke","Haskell Moore","Tadeusz Kesselring","Nurse Noa│
│ │ │kes","Boardman Mephi","Old Georgie"]} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Jessica Thompson"│"REVIEWED" │{"summary":"An amazing journey","rating":95} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Stefan Arndt" │"PRODUCED" │{} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Tom Hanks" │"ACTED_IN" │{"roles":["Zachry","Dr. Henry Goose","Isaac Sachs","Dermot Hoggins"]} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Jim Broadbent" │"ACTED_IN" │{"roles":["Vyvyan Ayrs","Captain Molyneux","Timothy Cavendish"]} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Halle Berry" │"ACTED_IN" │{"roles":["Luisa Rey","Jocasta Ayrs","Ovid","Meronym"]} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Lilly Wachowski" │"DIRECTED" │{} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"David Mitchell" │"WROTE" │{} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Tom Tykwer" │"DIRECTED" │{} │
├──────────────────┼─────────────────┼──────────────────────────────────────────────────────────────────────┤
│"Lana Wachowski" │"DIRECTED" │{} │
Instead get subscript out of bonds error
Error in .x[[i]] : subscript out of bounds
last_error
> rlang::last_error()
<error>
message: Each column must either be a list of vectors or a list of data frames [roles]
class: `rlang_error`
backtrace:
1. neo4r::unnest_relationships(res$relationships)
3. tidyr:::unnest.data.frame(relationships_tbl)
Call `rlang::last_trace()` to see the full backtrace
> rlang::last_trace()
█
1. └─neo4r::unnest_relationships(res$relationships)
2. ├─tidyr::unnest(relationships_tbl)
3. └─tidyr:::unnest.data.frame(relationships_tbl)
Traceback
30. $is_atomic(.x)
29. $modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic)
28. $.f(.x[[i]], ...)
27. $modify.default(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
26. $modify(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
25. $modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic)
24. $.f(.x[[i]], ...)
23. $modify.default(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
22. $modify(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
21. $modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic)
20. $.f(.x[[i]], ...)
19. $modify.default(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
18. $modify(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
17. $modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic)
16. $.f(.x[[i]], ...)
15. $modify.default(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
14. $modify(.x, function(x) { modify_depth_rec(x, .depth - 1, .f, ..., .ragged = .ragged, .atomic = .atomic) })
13. $modify_depth_rec(.x, .depth, .f, ..., .ragged = .ragged, .atomic = FALSE)
12. $modify_depth.default(results, vec_depth(results) - 1, function(x) { if (is.null(x)) { NA } ... $11. $modify_depth(results, vec_depth(results) - 1, function(x) { if (is.null(x)) { NA } ... $10. $parse_api_results(res = res, type = type, format = format, include_stats = include_stats, meta = include_meta)
9. $call_neo4j(., con, type = "row")
8. $function_list[[k]](value)
7. $withVisible(function_list[[k]](value))
6. $freduce(value, `_function_list`)
5. $`_fseq`(`_lhs`)
4. $eval(quote(`_fseq`(`_lhs`)), env, env)
3. $eval(quote(`_fseq`(`_lhs`)), env, env)
2. $withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
1. $"MATCH (people:Person)-[relatedTo]-(:Movie {title: 'Cloud Atlas'}) RETURN people.name, Type(relatedTo), relatedTo" %>% call_neo4j(con, type = "row")
Following #16
Here is the output of my reprex file:
library(neo4r)
library(httr)
con <- neo4j_api$new(url = "http://107.23.190.94:33961", user = "codes", password = "codes")
con
#> <Neo4JAPI>
#> Public:
#> access: function ()
#> auth: Y29kZXM6Y29kZXM=
#> clone: function (deep = FALSE)
#> get_constraints: function ()
#> get_labels: function ()
#> get_relationships: function ()
#> get_schema: function ()
#> get_version: function ()
#> initialize: function (url, user, password)
#> password: codes
#> ping: function ()
#> reset_password: function (password)
#> reset_url: function (url)
#> reset_user: function (user)
#> url: http:/107.23.190.94:33961
#> user: codes
con$get_version()
#> Error in curl::curl_fetch_memory(url, handle = handle): Could not resolve host: http
x <- GET("http://107.23.190.94:33961")
x
#> Response [http://107.23.190.94:33961/]
#> Date: 2018-04-05 04:58
#> Status: 200
#> Content-Type: application/json; charset=UTF-8
#> Size: 151 B
#> {
#> "management" : "http://107.23.190.94:33961/db/manage/",
#> "data" : "http://107.23.190.94:33961/db/data/",
#> "bolt" : "bolt://107.23.190.94:33960"
I get the error message could not resolve host: http
also by trying to execute con$ping(). The same error comes also by using a local Neo4j instance with http:\\localhost:7474
and by trying to connect from my Databricks Notebook.
Do you need any information about my local environment? I use Linux Mint if it makes any difference.
I create a graph using the Neo4j movie graph database with "graph" as the output type and then use convert_to with "igraph"
> G<-"MATCH a=(p:Person {name: 'Tom Hanks'})-[r:ACTED_IN]->(m:Movie) RETURN a;" %>%
call_neo4j(con, type = "graph") %>%
convert_to("igraph")
I get the following error referencing G:
> G
IGRAPH 35b7516 DN-- 13 12 --
+ attr: name (v/c), label (v/c), tagline (v/c), title (v/c), released
| (v/n), born (v/n), type (e/c), id (e/c), properties (e/x)
+ edges from 35b7516 (vertex names):
Error in if (is.na(no)) no <- len : argument is of length zero
Am thinking it might part of a different, but seemingly related error unnesting relationships when returned as a data.frame and not a graph:
> G<-"MATCH a=(p:Person {name: 'Tom Hanks'})-[r:ACTED_IN]->(m:Movie) RETURN a;" %>%
call_neo4j(con, type = "graph")
> unnest_nodes(G$nodes)
# A tibble: 13 x 7
id label tagline title released born name
<chr> <chr> <chr> <chr> <int> <int> <chr>
1 148 Movie Houston, we have a problem. Apollo 13 1995 NA NA
2 71 Person NA NA NA 1956 Tom H…
3 67 Movie At odds in life... in love on-… You've Go… 1998 NA NA
4 170 Movie Once in a lifetime you get a c… A League … 1992 NA NA
5 78 Movie A story of love, lava and burn… Joe Versu… 1990 NA NA
6 85 Movie In every life there comes a ti… That Thin… 1996 NA NA
7 111 Movie Break The Codes The Da Vi… 2006 NA NA
8 105 Movie Everything is connected Cloud Atl… 2012 NA NA
9 158 Movie At the edge of the world, his … Cast Away 2000 NA NA
10 130 Movie Walk a mile you'll never forge… The Green… 1999 NA NA
11 73 Movie What if someone you never met,… Sleepless… 1993 NA NA
12 169 Movie This Holiday Season… Believe The Polar… 2004 NA NA
13 167 Movie A stiff drink. A little mascar… Charlie W… 2007 NA NA
> unnest_relationships(G$relationships)
Error: Can't coerce element 1 from a list to a character
As a user that is developing locally, when I look at ?neo4j_api, I see this as the example:
neo4j_api$new(url = "http://localhost:7474", user = "neo4j", password = "password")
As I believe this is a common pattern and set of credentials, I expected to run:
con <- neo4j_api$new()
to authenticate and then
con$ping()
to return a 200
.
Basically, unless the user supplies values as they would for something beyond local dev efforts, it might be easier to have the defaults set for quick authentication.
This is a feature request, not a bug.
It's useful to be able to pass data as "parameters" in the queries.
(E.g. to load json, see https://neo4j.com/blog/cypher-load-json-from-url/)
I've updated the code in my fork below. Seems to be working so far... if it helps.
(Not doing a pull request as I've not tried every potential impact...)
to_json_neo <- function(query, params, include_stats, meta, type) {
toJSON(
list(
statement = query,
parameters = params,
includeStats = include_stats,
meta = meta,
resultDataContents = list(type)
),
auto_unbox = TRUE
)
}
I wanted to play around with these projects and started with the README. However, I can't ping the server, see below:
options(stringsAsFactors = FALSE)
## load libraries
install.packages("remotes")
remotes::install_github("neo4j-rstats/neo4r")
library(neo4r)
remotes::install_github("neo4j-rstats/play4j")
library(play4j)
## connect to neo4 3.3.0 from neo4j desktop
URL = "/Users/btibert/Library/Application Support/Neo4j Desktop/Application/neo4jDatabases/database-d2412486-df0a-43fb-8ec8-c578391fcaee/installation-3.3.0"
con <- neo4j_api$new(url = "http://localhost:7474", user = "neo4j", password = "password")
con$ping()
results in the error
> con$ping()
Error: attempt to apply non-function
my session info
> sessionInfo()
R version 3.4.4 RC (2018-03-08 r74373)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: OS X El Capitan 10.11.6
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] bindrcpp_0.2.2 tidyjson_0.2.1.9000 play4j_0.0.0.9000 neo4r_0.0.0.9000 tibble_1.4.2 purrr_0.2.4
[7] tidyr_0.8.0 dplyr_0.7.4 jsonlite_1.5
loaded via a namespace (and not attached):
[1] igraph_1.2.1 Rcpp_0.12.16 knitr_1.20 bindr_0.1.1 magrittr_1.5 tidyselect_0.2.4 R6_2.2.2
[8] rlang_0.2.0 stringr_1.3.0 httr_1.3.1 tools_3.4.4 remotes_1.1.1 htmltools_0.3.6 rprojroot_1.2
[15] digest_0.6.15 yaml_2.1.18 assertthat_0.2.0 attempt_0.2.0 base64enc_0.1-3 curl_3.2 evaluate_0.10.1
[22] glue_1.2.0 rmarkdown_1.6 stringi_1.1.7 compiler_3.4.4 pillar_1.2.1 backports_1.1.1 pkgconfig_2.0.1
Using the movie graph database I get an error with unnest_relationships. Output followed by clean code below:
`
library(remotes)
remotes::install_github("neo4j-rstats/neo4r")
Skipping install of 'neo4r' from a github remote, the SHA1 (0f2054e) has not changed since last install.
Use 'force = TRUE' to force installation
library(neo4r)
neo4jServerURL <- "http://localhost:7474"
neo4jUser <- "neo4j"
neo4jPassword <- "admin"
con <- neo4j_api$new(url = neo4jServerURL, user = neo4jUser, password = neo4jPassword)
res <- "MATCH (tom:Person {name: 'Tom Hanks'})-[r:ACTED_IN]->(tomHanksMovies) RETURN *;" %>% call_neo4j(con, type = "graph")
node_data <<- as.data.frame(unnest_nodes(res$nodes))
edge_data <<- as.data.frame(unnest_relationships(res$relationships))
Error: Can't coerce element 1 from a list to a character
`
library(remotes)
remotes::install_github("neo4j-rstats/neo4r")
library(neo4r)
neo4jServerURL <- "http://localhost:7474"
neo4jUser <- "neo4j"
neo4jPassword <- "admin"
con <- neo4j_api$new(url = neo4jServerURL, user = neo4jUser, password = neo4jPassword)
res<-"MATCH (tom:Person {name: 'Tom Hanks'})-[r:ACTED_IN]->(tomHanksMovies) RETURN *;" %>% call_neo4j(con, type = 'graph')
node_data<<-as.data.frame(unnest_nodes(res$nodes))
edge_data<<-as.data.frame(unnest_relationships(res$relationships))
Info: Neo4j needs to be run once on http://localhost:7474 to change password to "pouetpouet".
I notice when I use the Norwegian band dataset where the relationships have no attributes then unnest_relationships works perfectly.
However, when I test it with some of the movie data I run into one of the two following errors:
If there is just one attribute: Error: Can't coerce element 1 from a list to a character
If there are more than one: Error: Result 1 is not a length 1 atomic vector
I find just changing from map_chr to map seems to resolve the issue:
unnest_relationships <- function(relationships_tbl){
relationships_tbl$properties <- map(relationships_tbl$properties, na_or_self)
unnest(relationships_tbl, properties)
}
With the Norwegian band data it will still produce NAs however if there is a data set where some edges have attributes and others do not then it just shows NULL see example below:
## assumes active connection named con
'CREATE (matrix:Movie { title:"The Matrix",released:1997 })
CREATE (cloudAtlas:Movie { title:"Cloud Atlas",released:2012 })
CREATE (forrestGump:Movie { title:"Forrest Gump",released:1994 })
CREATE (keanu:Person { name:"Keanu Reeves", born:1964 })
CREATE (robert:Person { name:"Robert Zemeckis", born:1951 })
CREATE (tom:Person { name:"Tom Hanks", born:1956 })
CREATE (tom)-[:ACTED_IN { roles: ["Forrest","Frank"], acts: ["two","three"]}]->(forrestGump)
CREATE (tom)-[:ACTED_IN]->(cloudAtlas)
CREATE (robert)-[:DIRECTED]->(forrestGump)' %>%
call_api(con)
res <- 'MATCH p=()-[r:ACTED_IN]->() RETURN p' %>%
call_api(con, type = "graph")
neo4r::unnest_relationships(res$relationships) # results in an error
na_or_self <- function(x){
if(length(x) == 0) return(NA)
x
}
# switch from map_chr to map
unnest_relationships <- function(relationships_tbl){
relationships_tbl$properties <- map(relationships_tbl$properties, na_or_self)
unnest(relationships_tbl, properties)
}
unnest_relationships(res$relationships) # I believe this produces the desired result
Unfortunately, I am not finding a way to retain the NAs in these cases.
Following #22
I have the same problem in Neo4r than others persons (I can't do the connection with Neo4J), I can connect my R session 3.5.2 in R studio 1.1.4 in to Ne4j host this is the error:
con <- neo4j_api$new(url = "http://localhost:7474", user = "neo4j", password = "neo4j")
con$ping()
"Error: Failed to connect to localhost port 7474: Connection refused"
I do the change in to connected function neo4j_api$new
neo4j_api <- R6::R6Class("Neo4JAPI",
public = list(
url = character(0),
user = character(0),
password = character(0),....
but this doesn't work.
Installation fails due to a lack of a comma between tidyselect
and utils
in the imports section of the DESCRIPTION file.
PR #34 fixes the issue.
Still R6 default right now
These results should be gathered into one.
call_neo4j("MATCH (n) RETURN distinct labels(n)", con)
yields a single line result,
While on the admin webpage of the server I get a list of mulitple records.
What am I doing wrong?
There are no Vignette for now in the package (which is a bad thing).
The "Intro to {neo4r}" could be more or less a copy of the current README.
We could set the con
object to keep track of every call we are making to the API with this object, just to keep a kind of log file inside the object.
i.e : every time you run call_api("MY CALL", con)
, the con
object get the time, the call, and the resulting stats.
'CREATE CONSTRAINT ON (d:Day) ASSERT d.name IS UNIQUE' %>%
call_api(con, include_stats = TRUE)
# Will add to the con object :
Call `CREATE CONSTRAINT ON (d:Day) ASSERT d.name IS UNIQUE` at XX
# A tibble: 12 x 2
type value
<chr> <dbl>
1 contains_updates 1.
2 nodes_created 0.
3 nodes_deleted 0.
4 properties_set 0.
5 relationships_created 0.
6 relationship_deleted 0.
7 labels_added 0.
8 labels_removed 0.
9 indexes_added 0.
10 indexes_removed 0.
11 constraints_added 1.
12 constraints_removed 0.
Would it make sense?
We can do that with a local Docker image and skip this test on CRAN, and with Travis.
Started working on it here https://github.com/neo4j-rstats/neo4r/blob/master/R/as.R, but I'm not happy with the complexity of the current implementation.
Complementary to #1
nodbi is a unified NoSQL database interface, hope to integrate into nodbi, which means NoSQL DBI.
Something that could do :
'MATCH p=()-[r:MAINTAINS]->() RETURN p' %>%
call_api(con, type = "graph")%>%
extract_nodes()
# A tibble: 191 x 3
id label properties
<chr> <list> <list>
1 0 <chr [1]> <list [5]>
2 1 <chr [1]> <list [1]>
3 2 <chr [1]> <list [5]>
4 3 <chr [1]> <list [1]>
5 4 <chr [1]> <list [5]>
6 5 <chr [1]> <list [1]>
7 6 <chr [1]> <list [5]>
8 7 <chr [1]> <list [1]>
9 8 <chr [1]> <list [5]>
10 9 <chr [1]> <list [5]>
# ... with 181 more rows
So you can
'MATCH p=()-[r:MAINTAINS]->() RETURN p' %>%
call_api(con, type = "graph") %>%
extract_nodes() %>%
dplyr::count(names)
as_nodes
function is not (for now) working in a robust way for now
See : https://github.com/neo4j-rstats/neo4r/blob/master/R/as.R
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.