Can I store a list or array in Neo4j

I have some properties that are linked together by one common meta-property. So consider this ( it does NOT work - I know that)

CREATE (n:Person { name: 'Andy', title: 'Developer', listKey: [{ inner1: 'Map1' }, { inner2: 'Map2' }] })

The goal is to be able to manipulate this much like a dictionary in python or even a map. I could make them all properties

CREATE (n:Person { name: 'Andy', title: 'Developer', Inner1: 'Map1', Inner2: 'Map2' })

but that rather makes grouping (e.g. listKey) impossible.

This variant (straight up list) didnt work either -

CREATE (n:Person { name: 'Andy', title: 'Developer', listKey: [ inner1: 'Map1',  inner2: 'Map2' ] })

While these two are pretty clumsy, they work. But they require the developers to "unpack"

CREATE (n:Person { name: 'Andy', title: 'Developer', listKey: [" inner1: 'Map1", " inner2: 'Map2'"] })
CREATE (n:Person { name: 'Andy', title: 'Developer', listKey: " [ inner1: 'Map1',  inner2: 'Map2' ]" })

This works, and the java developers could at least create a Map structure, but makes the pure cypher developers a bit crazed ( not even sure how they would address the values)

CREATE (n:Person { name: 'Andy', title: 'Developer', listKeyN: [" inner1", " inner2"] , listKeyV:['Map1','Map2']})

I've seen some recommendation to add nodes and rel but given that I have 3m nodes, multiplying it by 20 doesn't seem smart. Although I could name the relationships listKey and walk the set.

Any other choices ? Is this something I should be doing in APOC ?

Thanks

May be considered a lame method, but still... JSON may be useful in your particular case.
Storing the listKey as a single String property and using apoc.convert.toJson / apoc.convert.fromJsonList / apoc.convert.fromJsonMap to manipulate its contents.
I'm also interested if anyone comes with something better :slight_smile:

Hello @bill.dickenson,

This line is the right way:

CREATE (n:Person { name: 'Andy', title: 'Developer', Inner1: 'Map1', Inner2: 'Map2' })

Otherwise, as said by @m-zielinski, store as JSON is a good option.

You can get on this page the values and type you can store as properties :slight_smile:

Regards,
Cobra

So far, you may be right. It just makes it easier for the UI developers to pick on different "listkey" groups in the interface rather than have to look it up. So if we move a variable from one group to another, we have to rely on documentation, and not just let them pull listkey1, listkey2 and use the structure to dictate what variables pop up. The closest we have come, is to create 3 "subnodes" for each and then link them through the main node.

image

Then the developers at least know to walk the set (e.g listkey2) but the mechanics of creating new nodes and managing seems cumbersome also. (especially through APOC) .

Are there any examples of using APOC and JSON functionality available publicaly ?

While not the optimal solution, we have almost settled in on two linked lists,

CREATE (n:Person { name: 'Andy', title: 'Developer', listKey1Name: [" inner1", " inner2"] , listKey1Value:['Map1','Map2'],listKey2Name: [" inner3", " inner4"] , listKey2Value:['Map3','Map4']})

It's a compromise, since the developers can have a UI element (listKey1, listKey2) that can be exploded (think "+") into elements

(-) listKey1
     inner1:map1
	 inner2:map2
(+) listkey2	

How did you store the data in the nodes?
Can you print the content of a node?

Right now, we store it as a big string and then parse in java. Focus on the listKey strings.

{
  "identity": 1,
  "labels": [
    "Label",
    "ProgNode",
    "data:Reads"
  ],
  "properties": {
"level": "code",
"ctx": "1891845967",
"Label": "data:Reads",
"FILECOUNT": 1,
"listKey1": "{'time':0, 'calls':0, 'score':0}",
"listKey2": "{'reusescore':0, 'called':0, 'score':0}",
"type": "typeImportOnDemandDeclaration",
"EIEO": true,
"inode": "1",
"node": "1",
"location": [
      16,
      0,
      16,
      17
    ],
"text": "importjava.net.*;",
"changed": false
  }
}

In a perfect world, we would not have to do this but this is the structure the UI developers and the rule developers have agreed on. It would replace listkey1, listkey2 with something like

"listKey1Name": ['time','calls','score'],
"listKey1Value": [0,0,0],

which could be zip into a single key:value list for the UI (referring to the zip(list, list, list) call that combines lists)

Thanks

Of course now I need to figure out how to access the listKey1Value list in cypher - so not ideal.

Might have a huge overhead and cypher complexity, but how about having one node for each property type (like time), and, for each node that would have had that property in the map, a relationship with that node. And then use a relationship property with the value of that field.

Null properties could be represented as no relationship, and you can still perform queries using the operators on the relationship values.

Like, one single node for "time" property type, and a generic val property with in each relationship with nodes that have that property in the map?

I hope this helps.

Cheers,

I say you treat the Graph DB as a Graph DB, and create a linked list of nodes faithfully represented as nodes and arrows in the global graph itself.

class LinkedListNode(StructuredNode):
       uid = UniqueIdProperty()
       next_uid = StringProperty()
       data_uid = StringProperty()

That is the neomodel code to do this. :D I am having some success with Django + associated neomodel libraries in Python.

Tried that. It increased (slowed down) the system about 15-18% so it wasn't viable. But thanks for following up !

1 Like

Hello :slight_smile:

It looks like that now you can store homogeneous type lists, for example: list of integers, list of strings or list of Points.

Regards,
Cobra

Yes, thank you. That was exactly how we ended up solving the problem. It was much simpler.

@bill.dickenson @Cobra where have you seen that?
When checking the 4.2 documentation, it says:

Cannot be stored as properties

EDIT: how, my bad... I've now found it in "Property types"

Homogeneous lists of simple types can also be stored as properties, although lists in general (see Composite types) cannot be stored.

But as Cobra said, its homogeneous - so no mixed int/string lists. That wasn't fatal, we just made everything a string and converted the ones that were really integers on the back end.

2 Likes