Virtual Graph
Create a graph object (map) from information that’s passed in.
Its basic structure is: {name:"Name",properties:{properties},nodes:[nodes],relationships:[relationships]}
Qualified Name | Type | Release |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apoc.graph.fromDocument
The procedure apoc.graph.fromDocument
transforms a JSON into a graph structure.
It takes two arguments:
-
json, type Object: the JSON that must be transformed. Every entry must have an
id
and atype
(name of Label), configurable via the config params.
The value can be a String, or Cypher Map or List of Maps. -
config, type Map: the configuration params
Currently spatial and datetime properties are not handled yet. More advanced configuration for mapping the document is coming in future versions.
The config is composed by the following parameters:
-
write, type boolean: persist the graph otherwise return a Virtual Graph, default false
-
labelField, type String: the field name that became the label of the node, default type
-
idField, type String: the document field name that will become the id field of the created nodes (used for node resolution when you create relationships between nodes), default id
-
generateId, type boolean: in case of missing id-field value it generates an UUID for it, default true
-
defaultLabel, type String: in case of missing label-field value is uses the provided default label, default is empty
-
skipValidation, type boolean: in case you want skip the validation process into the
apoc.graph.fromDocument
procedure false -
mappings, type Map<String, String>: you can use a JSON path like syntax for:
-
include properties
-
defining document properties as value objects, by prepending the
@
to the property name -
define custom/composite keys per Labels, by prepending the
!
to the property name
-
Following an example of configuration with mappings:
{
write: false,
idField: "id",
mappings: {
`$`: 'Person:Reader{*,@size}'
`$.books`: 'Book{!title, released}'
}
}
Lets describe the mappings:
-
$
: 'Person:Reader{*,@size}': this means that at the root object will be applied two labelsPerson
andReader
, all properties are included and thesize
property will be transformed into a value objects as you can see no id is specified so we will consider as id the property defined into theidField
-
$.books
: 'Book{!title, released}': this means that at thebooks
property of the root object will transformed into a node with label Book composed by two propertiestitle
considered as id (it’s marked with!
) andreleased
moreover the property will be connected to the parent node of typePerson:Reader
via theBOOKS
relationship
{
"id": 1,
"type": "artist",
"name": "Genesis",
"members": ["Tony Banks", "Mike Rutherford", "Phil Collins"],
"years": [1967, 1998, 1999, 2000, 2006]
}
In this case it create one Node
with labels Artist
It also accepts list of documents:
[{
"id": 1,
"type": "artist",
"name": "Genesis",
"members": ["Tony Banks", "Mike Rutherford", "Phil Collins"],
"years": [1967, 1998, 1999, 2000, 2006]
}, {
"id": 2,
"type": "artist",
"name": "Daft Punk",
"members": ["Guy-Manuel de Homem-Christo", "Thomas Bangalter."],
"years": [1987, 1993, 1999, 2004, 2008, 2011]
}]
In this case it create 2 Node
with labels Artist
JSON Tree to graph:
{
"id": 1,
"type": "artist",
"name": "Genesis",
"albums": [{
"type": "album",
"id": 1,
"producer": "Jonathan King",
"title": "From Genesis to Revelation"
}]
}
In this case it will create 2 Node
, one Artist and one Album connected to each other by the ALBUMS Relationship
apoc.graph.validateDocument
The procedure apoc.graph.validateDocument
validate the JSON and returns information about required fields violations.
It takes same arguments as apoc.graph.fromDocument
Virtual Graph Examples
We create a dataset for our examples
CREATE (a:Actor {name:'Tom Hanks'})-[r:ACTED_IN {roles:'Forrest'}]->(m:Movie {title:'Forrest Gump'})
RETURN *
MATCH (n)-[r]->(m) CALL apoc.graph.fromData([n,m],[r],'test',{answer:42})
YIELD graph
RETURN *
MATCH path = (n)-[r]->(m) CALL apoc.graph.fromPath(path,'test',{answer:42})
YIELD graph
RETURN *
MATCH path = (n)-[r]->(m) CALL apoc.graph.fromPaths([path],'test',{answer:42})
YIELD graph
RETURN *
CALL apoc.graph.fromDB('test',{answer:42})
YIELD graph
RETURN *
CALL apoc.graph.fromCypher('MATCH (n)-[r]->(m) RETURN *',null,'test',{answer:42})
YIELD graph
RETURN *
As a result we have a virtual graph object for later processing
CALL apoc.graph.fromDocument("{'id': 1,'type': 'artist','name':'Genesis','members': ['Tony Banks','Mike Rutherford','Phil Collins'],'years': [1967, 1998, 1999, 2000, 2006],'albums': [{'type': 'album','id': 1,'producer': 'Jonathan King','title': 'From Genesis to Revelation'}]}", {write: false})
YIELD graph
RETURN *
As a result we have a virtual graph with two nodes and one relationship:
CALL apoc.graph.fromDocument('{"id":10,"myCustomType":"labelArtist","name":"Genesis","albums":[{"myCustomType":"labelAlbum","producer":"Jonathan King","id":20,"title":"From Genesis to Revelation"}]}', {labelField: "myCustomType"})
YIELD graph
RETURN *
As a result we have a virtual graph with two nodes and one relationship:
CALL apoc.graph.fromDocument('{"myCustomType":"labelArtist","name":"Genesis","myCustomId":1,"albums":[{"myCustomType":"labelAlbum","producer":"Jonathan King","myCustomId":1,"title":"From Genesis to Revelation"}]}',
{labelField: "myCustomType", idField: "myCustomId"})
YIELD graph
RETURN *
As a result we have a virtual graph with two nodes and one relationship:
CALL apoc.graph.fromDocument('{"id":1,"type":"Person","name":"Andrea","sizes":{"weight":{"value":70,"um":"Kg"},"height":{"value":174,"um":"cm"},"array":["foo","bar"]},"books":[{"title":"Flow My Tears, the Policeman Said","released":1974},{"title":"The man in the High Castle","released":1962}]}',
{mappings:{`$`:"Person:Reader{*,@sizes}",`$.books`:"Book{!title, released}"}})
yield graph
RETURN *
As a result we have a virtual graph with three nodes and two relationship:
In case this json:
{
"id": 1,
"type": "Person",
"name": "Andrea",
"sizes": {
"weight": {
"value": 70,
"um": "Kg"
},
"height": {
"value": 174,
"um": "cm"
}
}
}
You can manage the sizes
property as value object so you manage it as follows:
call apoc.graph.validateDocument(<json>, {mappings: {`$`: "Person{*,@sizes}"}})
So the procedure will create a node with the following properties:
{
"id": 1,
"type": "Person",
"name": "Andrea",
"sizes.weight.value": 70,
"sizes.weight.um": "Kg",
"sizes.height.value": 174,
"sizes.height.um": "cm"
}
As specified you can also provide a set of value-object properties for a Label:
call apoc.graph.validateDocument(<json>, {mappings: {`$`: "Person{*,@sizes}"}})
You can also do a pre-validation over the document with the apoc.graph.validateDocument
procedure that will return the
record with invalid data.
call apoc.graph.validateDocument('[{"foo": "foo"}, {"bar": "bar", "id": 1, "type": "label"}, {"fooBar": "fooBar", "id": 1}]')
or
call apoc.graph.validateDocument([{foo: "foo"}, {bar: "bar", id: 1, type: "label"}, {fooBar: "fooBar", id: 1}])
Will display the following result: