For example, given node types User and Post, and expressing that a user posted something on Twitter, what factors would I need to consider in deciding between:

(u:User)-[posted]->(p:Post {platform: 'twitter'}),

(u:User)-[posted {platform: 'Twitter'}]->(p:Post)



It seems like each approach is valid but likely optimal under different circumstances.

Specifically, I'm using Neo4j in this case.

2 Answers 2


Some things to think of are what your use case is and what the most likely queries will be. Depending on your graph, and I don't know specifically about neo4j, attributes on nodes and edges may create a lot of data duplication if each node or edge stores a copy of the same attribute.

If you link to a node like the the third example, you may save data duplication but you have to store more edges.

If you are often querying as to where something was posted, an attribute may prove more performant than having to traverse another edge.

It also depends on how you are accessing the data: via some micro service or in embedded mode for neo4j, or if some other graph model maybe in memory?

As an example from my own work: I am reworking a graph model we have, we use it both in memory and via a micro service for different use cases. Some in depth testing finally led us to have two different implementations for the same data. The in memory copy being specifically designed to provide quick queries on the most commonly expected query types for that use case and the micro service model, housing the same data storing it for more efficient queries on its most common query types.

  • I'll be filtering on platform type a lot, so I think that makes the third option worst (at least for that case). Presumably, then, the second option also means that Post nodes can be filtered out without having to look at them, which is even better.
    – Isvara
    Commented Mar 11, 2018 at 5:34
  • Would doing so be the equivalent of denormalization in a relational database?
    – Isvara
    Commented Mar 11, 2018 at 5:34
  • Ah, but if I wanted to get, say, all the Twitter posts without regard for who posted them, I'd want the property on the Post nodes.
    – Isvara
    Commented Mar 11, 2018 at 10:23
  • 1
    As you are seeing there are a lot of options and considerations. I really don't know a best answer. You may want to construct multiple example data sets and then run some tests on what are/expected to be common queries. When I last looked into neo4j it did have a very good profiling tool from what I remember. The other thing to take into consideration is actual requirements. You might find after running a bunch of tests that every model is essentially the same given your functional requirements. At which point I would opt for the model that is easiest to work with. Commented Mar 11, 2018 at 18:28

I think it is important to construct a model of the data that captures the business domain's understanding. The nodes and edges will flow naturally from that. This touches on ontology, too.

If I construct a sequence of words, and send it to Twitter, and then send the same words to Facebook, have I made two distinct POSTs or one POST to two platforms? Which of these definitions is important in the application's problem domain.

For a marketing campaign, say, I could understand that it would be a single message on multiple platforms. Alternatively, if I were gauging an individual's use of social media I may consider them distinct. Context is everything.

If posts are distinguished by platform then platform is an attribute of post. If they see it as a single post but it is the act of distribution that is distinguishing then platform is an attribute of the relationship. If the user community had an on-going interest in Twitter of and by itself, not just as a target of posts, then Twitter should be a node, too. All three may be independently significant and we require a new node label "posting" with edges to user, post and to platform.

Implementing a logical data model as a physical database can often involve compromises. I think there may be one here. Neo4j stores a list of incoming and outgoing edges on each node. If there are a great many posts to, say, Twitter then updating the edge list will become a bottleneck.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.