0
votes

I'm creating a simple social graph where a user can create a post, tag it, and comment on it. I'm using py2neo to do the modelling. The model has user and post as nodes. A user TAGGED, POSTED, or COMMENTED on a post. In my case, a single user can create multiple tags or comments on a single post (just like any social network out there). Based on my model, this necessitates multiple TAGGED or COMMENTED relationships but with distinct properties. The model is built thusly:

from py2neo.ogm import (
    GraphObject, 
    Property, 
    RelatedTo, 
    RelatedFrom
)


class User(GraphObject):
    __primarykey__ = 'name'

    name = Property()

    posts = RelatedTo('Post', 'POSTED')
    comments = RelatedTo('Post', 'COMMENTED')
    tags = RelatedTo('Post', 'TAGGED')

    def __init__(self, name):
        self.name = name


class Post(GraphObject):

    # assumes __id__ as primary key because
    # left undefined

    title = Property()

    users = RelatedFrom('User', 'POSTED')
    comments = RelatedFrom('User', 'COMMENTED')
    tags = RelatedFrom('User', 'TAGGED')

    def __init__(self, title):
        self.title = title

I run the following to build the graph:

user = User(name='john')
post = Post(title='Wow!')

user.posts.add(
    post,
    {'date': '2017-04-26'}
)
graph.push(user)

user.comments.add(
    post,
    {'caption': 'I know!', 'date': '2017-04-26'}
)
graph.push(user)

for tag in ['yellow', 'green']:
    user.tags.add(
        post,
        {'tag': tag, 'date': '2017-04-26'}
    )
    graph.push(user)

I would expect there to be two TAGGED relationships, something like this:

Expecting to see

But I see this is not the case:

enter image description here

My question then is twofold. (1) Can create a multiple relationships of the same type with different properties? (2) Is this the best model choice for the use case?

2

2 Answers

1
votes

You can use neo4jrestclient. It alows you to have multiple relationships of the same type and it's quite easy to use too. You can use the following code:

    from neo4jrestclient.client import GraphDatabase
    gdb=GraphDatabase("http://localhost:7474/db/data/")
    user=gdb.nodes.create(name='john')
    post=gdb.nodes.create(title='wow')
    user.labels.add('User')
    post.labels.add('Post')
    u=gdb.labels.get('User')
    p=gdb.labels.get('Post')

now for multiple relationships

    for tag in ['yellow', 'green']:
        u.get(name='john')[0].relationships.create('TAGGED',p.get(id=0)[0],tag=tag,date='2017-04-26')

this should do it. The .get is used to update a node much like .push. And there can be much cleaner way to do this, but you get the idea. The documentation is pretty decent too. https://readthedocs.org/projects/neo4j-rest-client/downloads/pdf/latest/

0
votes

Although neo4j (and most programming interfaces to neo4j, like Cypher) does support multiple relationships of the same type (with possibly differing property sets) between a single pair of nodes, py2neo does not seem to (see this issue).

I suggest that you consider using some other way to use neo4j from Python, like the officially supported neo4j Python Driver.