Search code examples
pythonneo4jgraph-databasesbulbs

Bulbflow – How to save list/dictionary as property


I am using Bulbflow to access Neo4j through python.

I'm now trying to save a python list as a node property, but am consistently running into errors. From the documentation, I can see that lists are an accepted type when defined in models, but I'd like to save a list property after the models are defined, i.e.

anode = g.vertices.get(123)
anode.specs = [(2, 0.27911702036756064), (5, 0.6708785014712791)]
anode.save()

But I get the following error:

SystemError: (
   {'status': '200',
    'content-length': '142',
    'content-type': 'application/json; charset=UTF-8',
    'access-control-allow-origin': '*',
    'server': 'Jetty(6.1.25)'},
    '"java.lang.IllegalArgumentException:
        Unknown property type on: [[2, 0.27911702036756064], [5, 0.6708785014712791]],
        class java.util.ArrayList"')

I tried using the convert_to_db function, but wasn't sure what the syntax was.

Any ideas on how to achieve this? Is the problem that I have a list of tuples?

Thanks!

============== UPDATE ==============

Following Peter's suggestion, I tried the same with a simple flat list and ran into the same error:

SystemError: (
    {'status': '200',
     'content-length': '172',
     'content-type': 'application/json; charset=UTF-8',
     'access-control-allow-origin': '*',
     'server': 'Jetty(6.1.25)'},
     '"java.lang.IllegalArgumentException:
         Unknown property type on: [0.0, 0.0, 0.0, 0.42659109777029425, 0.0, 0.0, 0.0, 0.0, 0.5234052770685714, 0.0],
         class java.util.ArrayList"')

Any ideas?


Solution

  • Neo4j only supports lists that contain primitive types such as string, int, bool, etc (mixed types in a list aren't allowed).

    Here are the property types Neo4j supports:

    http://docs.neo4j.org/chunked/preview/graphdb-neo4j-properties.html

    To store a mixed-type list in Neo4j, you can save it as a JSON document string.

    Bulbs has a Document Property type that does the dict<->json conversion for you.

    See...

    If you working with a generic Vertex or Edge, you need to do this conversion manually before you save it:

    specs = [(2, 0.27911702036756064), (5, 0.6708785014712791)]
    anode = g.vertices.get(123)
    anode.specs = g.client.type_system.database.to_document(specs)
    anode.save()
    

    However, if you are using a Model, Bulbs will do the conversion for you. Simply define your model using the Document property instead of List:

    # people.py
    
    from bulbs.model import Node, Relationship
    from bulbs.property import String, DateTime, Document
    from bulbs.utils import current_datetime
    
        class Person(Node):
    
            element_type = "person"
    
            name = String(nullable=False)
            specs = Document()
    
        class Knows(Relationship):
    
            label = "knows"
    
            timestamp = DateTime(default=current_datetime, nullable=False)
    

    ...you can then use your model like this...

    >>> from people import Person, Knows
    >>> from bulbs.neo4jserver import Graph
    
    >>> g = Graph()
    >>> g.add_proxy("people", Person)
    >>> g.add_proxy("knows", Knows)
    
    >>> specs = [(2, 0.27911702036756064), (5, 0.6708785014712791)]
    
    # You can save specs when you create it...
    >>> james = g.people.create(name="James", specs=specs)
    
    # ...or save it after creation...
    >>> julie = g.people.create(name="Julie")
    >>> julie.specs = specs
    >>> julie.save()
    

    See http://bulbflow.com/docs/api/bulbs/model/