neo4jcypherneo4j-apocbloodhound

Neo4j error when importing json file via Cypher


I am trying to import a Bloodhound/SharpHound json file into Neo4j but I am running into the following error:

{ "Neo4j only supports a subset of Cypher types for storage as singleton or array properties. Please refer to section cypher/syntax/values of the manual for more details.": 1 }

This is my script:

call apoc.periodic.iterate('
call apoc.load.json("file:///sessions/20190822113758_groups.json") yield value
','
create (n:Groups) SET n += value
',{batchSize:10000})

this is what is in the json file:

{"domains":[{"Properties":{"objectsid":"S-1-2-2515432156546548","highvalue":true,"domain":"somethingone.COM"},"Name":"somethingone.COM","Links":null,"Trusts":[{"TargetName":"some.somethingtwo.COM","IsTransitive":true,"TrustDirection":2,"TrustType":"External"},{"TargetName":"something-three.COM","IsTransitive":true,"TrustDirection":2,"TrustType":"ParentChild"},{"TargetName":"somethingfour.COM","IsTransitive":true,"TrustDirection":0,"TrustType":"External"}],"Aces":null,"ChildOus":null,"Computers":null,"Users":null}],"meta":{"count":1,"type":"domains"}}

Solution

  • Neo doesn't support properties on nodes being maps, or arrays of maps. For example, neither of the following work:

    CREATE (n: Group) SET n.prop = { key: "value" }
    
    Neo.ClientError.Statement.TypeError: Property values can only be of primitive types or arrays thereof
    
    CREATE (n: Group) SET n.prop = [{ key: "value" }, { key: "value" }]
    
    Neo.ClientError.Statement.TypeError: Neo4j only supports a subset of Cypher types for storage as singleton or array properties. Please refer to section cypher/syntax/values of the manual for more details.
    

    The second is the error you're seeing, but they're basically equivalent - you're trying to add a property to a node with an unsupported data type. If you look at your JSON file, the domains map is itself an array of maps which themselves contain further maps...

    enter image description here

    You will need to think about what the graph structure is that you want to generate from the JSON file, and then instead of just CREATE (n: Group) n += value you'll probably need to UNWIND the value.domains array and create the nodes and properties by traversing the nested maps that represent the JSON.

    For example, the following would create Group nodes with a 'Name' property, and Trust nodes with the information from the Trusts array:

    call apoc.load.json("file:///sessions/20190822113758_groups.json") yield value
    UNWIND value.domains as domain
    MERGE (g: Group { Name: domain.Name })
    WITH g, domain.Trusts as trusts
    UNWIND trusts as trust
    MERGE (t: Trust { TrustType: trust.TrustType, TrustDirection: trust.TrustDirection, TargetName: trust.TargetName, IsTransitive: trust.IsTransitive })
    MERGE (t)-[:BELONGS_TO]->(g)
    RETURN t, g
    

    You may find you need to make multiple calls to apoc.load.json and create the graph in parts - maybe first creating Groups, then Trusts, then Properties and so on joining the nodes up as you go, it's hard to tell with all the nulls in the example JSON file.