3

Scenario: a simple address book where a user can create his own contacts and organize them by adding them in groups. A contact may have multiple addresses.

I have created the following diagram: ![schema-design][1]

I want to query all the contacts who are placed in group x and live in country y.

Is this schema design good enough for those purposes (I want to use the neo4j database)?

Moody
  • 851
  • 2
  • 9
  • 23

2 Answers2

3

It looks like the notion of country should be a first class citizen in your graph since your query depends on it. Graph model design typically gets influenced a lot by your query patterns.

So I suggest to have a node labeled Country for each country and connect the Address node with :LOCATED_IN relationships to the country. (consequently drop the country property from the address nodes).

With that change your query is as easy as:

MATCH (:Group{name:'family'})<-[:placed_in_group]-(contact)-[:lives-at]->()-[:LOCATED_IN]->(:Country{name:'US'})
RETURN contact
Stefan Armbruster
  • 39,465
  • 6
  • 87
  • 97
  • By the way, Stefan, do you by any chance have any comparison of statistics concerning how much do dense nodes affect performance in cases like this? Say I have ~20K nodes with the `Prop` property (maybe indexed on it as well) and I'm querying the DB just to find all the nodes which have the `Prop` and then filter on the concrete `Prop` value (the amount of possible Prop values is rather small: I can enumerate them all (say 1000 possible values)). Would it be a better design if I create a label `Prop` and create 20K relationships to it? What would be a better choice performance-wise? – tkroman Apr 02 '15 at 12:33
  • you need to be aware that you might run into locking issues if you connect concurrently a lot of addresses to the same country. Creating a relationship means locking its start and end node as well. However you can easily work around that by having couple of "docking nodes" around the country. The address then selects one docking node e.g. by consistent hashing on the thread id - this prevents locking issues. On the query side I don't have measurements available. – Stefan Armbruster Apr 02 '15 at 12:49
  • Hi Stefan, can you please take a look at my question too, it is almost same and about NEO4J http://stackoverflow.com/questions/37374675/how-to-store-social-networks-actions-in-neo4j – Mohammad Kermani May 22 '16 at 13:02
2

One option is to have another node from address for country, as pointed out by stefan Armbruster. If you do not want to change the data structure, just add an index to the field "country" of Address. Then you can have a query

MATCH (:Group{name:'family'})<-[:placed_in_group]-(contact)-[:lives-at]->(:Address{country:'US'})

gaurav.singharoy
  • 3,751
  • 4
  • 22
  • 25