Search code examples
jsonvariablesneo4jlabelcypher

How to create nodes with variable labels in cypher?


I am using JSON APOC plugin to create nodes from a JSON with lists in it, and I am trying to create nodes whose label is listed as an element in the list:

{
    "pdf":[
        {
            "docID": "docid1", 
            "docLink": "/examplelink.pdf", 
            "docType": "PDF"
        }
],
    "jpeg":[
        {
            "docID": "docid20", 
            "docLink": "/examplelink20.pdf", 
            "docType": "JPEG"
        }
],
...,}

And I want to both iterate through the doctypes (pdf, jpeg) and set the label as the docType property in the list. Right now I have to do separate blocks for each doctype list (jpeg: [], pdf:[]):

WITH "file:////input.json" AS url
CALL apoc.load.json(url) YIELD value
UNWIND value.pdf as doc
MERGE (d:PDF {docID: doc.docID})

I'd like to loop through the doctype lists, creating the node for each doctype with the label as either the list name (pdf) or the node's docType name (PDF). Something like:

WITH "file:////input.json" AS url
CALL apoc.load.json(url) YIELD value
for each doctypelist in value
for each doc in doctype list
MERGE(d:doc.docType {docID: doc.docID})

Or

WITH "file:////input.json" AS url
CALL apoc.load.json(url) YIELD value
for each doctypelist in value
for each doc in doctype list
MERGE(d {docID: doc.docID})
ON CREATE SET d :doc.docType

Solution

  • Cypher currently does not support this. To set a label, you must hardcode it into the Cypher. You could do filters, or multiple matches to do this in a tedious way, but if you aren't allowed to install any plug-ins to your Neo4j db, I would recommend either just putting an index on the type, or use a node+relation instead of the label. (There are a lot of valid doc types, so if you have to support them all, pure Cypher will make it very painful.)

    Using APOC however, there is a procedure specifically for this apoc.create.addLabels

    CREATE (:Movie {title: 'A Few Good Men', genre: 'Drama'});
    MATCH (n:Movie)
    CALL apoc.create.addLabels( id(n), [ n.genre ] ) YIELD node
    REMOVE node.genre
    RETURN node;