Jason Strimpel
Jason Strimpel

Reputation: 15466

Create same relationships between nodes with different properties

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?

Upvotes: 0

Views: 973

Answers (2)

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/

Upvotes: 1

cybersam
cybersam

Reputation: 66967

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.

Upvotes: 0

Related Questions