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]}

apoc.graph.from(data,'name',{properties}) yield graph

creates a virtual graph object for later processing it tries its best to extract the graph information from the data you pass in

apoc.graph.fromData([nodes],[relationships],'name',{properties})

creates a virtual graph object for later processing

apoc.graph.fromPaths(path,'name',{properties})

creates a virtual graph object for later processing

apoc.graph.fromPaths([paths],'name',{properties})

creates a virtual graph object for later processing

apoc.graph.fromDB('name',{properties})

creates a virtual graph object for later processing

apoc.graph.fromCypher('statement',{params},'name',{properties})

creates a virtual graph object for later processing

apoc.graph.fromDocument({json},{config})

transform JSON documents into graph structures

apoc.graph.validateDocument({json},{config})

validate the JSON and returns information about required fields violations

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 a type (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 labels Person and Reader, all properties are included and the size 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 the idField

  • $.books: 'Book{!title, released}': this means that at the books property of the root object will transformed into a node with label Book composed by two properties title considered as id (it’s marked with !) and released moreover the property will be connected to the parent node of type Person:Reader via the BOOKS 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 *
Virtual graph from data
MATCH (n)-[r]->(m) CALL apoc.graph.fromData([n,m],[r],'test',{answer:42})
YIELD graph
RETURN *
Virtual graph from path
MATCH path = (n)-[r]->(m) CALL apoc.graph.fromPath(path,'test',{answer:42})
YIELD graph
RETURN *
Virtual graph from paths
MATCH path = (n)-[r]->(m) CALL apoc.graph.fromPaths([path],'test',{answer:42})
YIELD graph
RETURN *
Virtual graph from DB
CALL apoc.graph.fromDB('test',{answer:42})
YIELD graph
RETURN *
Virtual graph from Cypher
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

apoc.graph
Virtual graph from JSON
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:

apoc.graph.fromDocument 1
Virtual graph from JSON with labelField
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:

apoc.graph.fromDocument with label type
Virtual graph from JSON with labelField and idField
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:

apoc.graph.fromDocument with label type and id field
Virtual graph from JSON with mappings
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:

apoc.graph.fromDocument with mappings

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:

apoc.graph.validateDocument