Can't create a node with nested sub-properties


(Dickersonc) #1

I have searched everywhere, but cannot find the answer to this.

I need to create a node Config that has a Properties object with 2 key/value pairs (name and type). The keys, when queried, should end up as properties.name and properties.type. But I cannot seem to get the create syntax right. This is what I'm doing:

CREATE (c1:Config) set c1.properties=[{name:"CiPipelineConfig1"}, {type:"test"}]

But that gives me some weird error:

Neo.ClientError.Statement.TypeError: Neo4j only supports a subset of Cypher types for storage as singleton or array properties.

Can anyone help me figure this query out?


(Mike R Black) #2

I could get this syntax to work but it may not be what you're looking for:

CREATE (c1:Config) 
SET c1.properties = ["CiPipelineConfig1","test"]
RETURN c1

I think you're going to get a lot of people wondering what the use case for storing your data this way instead of modeling it out in the graph.


(Dickersonc) #3

So are you suggesting that every Property be a node, instead of being the payload of node??


(Andrew Bowman) #4

Neo4j doesn't allow maps as properties (no sub-properties allowed, basically), and though lists are allowed as properties, they cannot be lists of maps (or lists of lists for that matter).

You can either use properties as-is on the node itself like (c1:Config {name:"CiPipelineConfig1", type:"test"}), or if you do need some means of grouping, create an additional connected node (or nodes) to hold the properties according to the grouping needed.


(Dickersonc) #5

What I meant to do was set each key/value pair separately, not as a map.


(Andrew Bowman) #6

Oh, so you want to set an entire map's worth of properties at once?

That's easy enough:

WITH {name:"CiPipelineConfig1", type:"test", foo:"bar"} as props
CREATE (c1:Config)
SET c1 = props

This will overwrite all properties with the contents in the properties map. Complete description within the Set section. of the Cypher documentation.

If you instead want to add the properties (overwriting existing properties of the same name) but keep the rest of the properties, use SET c1 += props


(Michael Hunger) #7

Or if they are just stored but not frequently used you can store them as JSON string.
APOC has a bunch of procedures/functions of automatically handling the conversions.


(Mike R Black) #8

This topic reminds me of a Neo4j Blog Post about best and worst practices. About a half way through the post it talks about storing blobs of data in Neo4j. Technically yes you could store very large strings, strings a of JSON even, but be weary of doing so. Neo4j is a graph database not a document database. If you have a need to store documents whose data doesn't make sense being stored as a graph, I'd recommend a polyglot persistence solution: store your graph data and in the properties of the nodes store the URL/ObjectId of that data. Then leverage other databases such as MongoDB or AWS S3 Buckets to store the actual document itself. A good example, a user's profile image. You'd want your user nodes but I'd store the JPG binary in an S3 bucket.