Collections containing mixed types can not be stored in properties

745 Views Asked by At

I am new to Neo4j, I am trying to create a node like so:

neo4_session.run("MERGE (t:Table {name: $name, columns: $columns}) ",
     name=table['table_name'], columns=[{'colname':'a'},{'colname':'b'},{'colname':'c'}])

Neo4j tells me this:

neo4j.exceptions.CypherTypeError: Collections containing mixed types can not be stored in properties.

Which means it only allows me to have a list:

neo4_session.run("MERGE (t:Table {name: $name, columns: $columns}) ",
     name=table['table_name'], columns=['a','b','c'])

However, each table node in my database will have different column names so I can't really have a list of properties...

Any advice?

2

There are 2 best solutions below

0
On BEST ANSWER

I think you should consider using a :Column node label instead of a list of columns in the :Table node.

This way you can model your graph like this:

CREATE (table:Table {name : 'Table 1'})
CREATE (columnA:Column {colname : 'a'})
CREATE (columnB:Column {colname : 'b', otherProp: 'Other value'})
CREATE (columnC:Column {colname : 'c'})
CREATE (table)-[:CONTAINS]->(columnA)
CREATE (table)-[:CONTAINS]->(columnB)
CREATE (table)-[:CONTAINS]->(columnC)

Resulting on:

Sample data

Also, this is a more "graphist" way to model your data.

2
On

The simplest approach is to just directly store each column as a property:

CREATE (table:Table {name: 'Table 1', colName1: 'a', colName2: 'b', colName3: 'c'})

And, if you need to access the columns in column-order for some reason, you could have an array, say colNames, that stores the ordered column names:

CREATE (table:Table {
  name : 'Table 1',
  colName1: 'a', colName2: 'b', colName3: 'c',
  colNames: ['colName1', 'colName2', 'colName3']
})

Also, see this related question and the third approach I suggested in my answer.

[UPDATE]

As indicated by @Tezra, the above CREATE clauses can be refined to just take a parameter whose value is a map dynamically generated by your code. For example, if this were passed as the $data parameter:

{
  name : 'Table 1',
  colName1: 'a', colName2: 'b', colName3: 'c',
  colNames: ['colName1', 'colName2', 'colName3']
}

then this CREATE clause would get the same results as my previous clause:

CREATE (table:Table $data)