Some simple use cases in Neo4j

First we import some simple data, containing nodes and relations into neo4j

neo4j-sh (?)$ CREATE (Client1:client {name:’Ants Konn’, age:34, sex:’M’})

> CREATE (Client2:client {name:’Ivan Orav’, age:66, sex:’M’})

> CREATE (Client3:client {name:’Kadri Kala’, age:24, sex:’F’})

> CREATE (Client4:client {name:’Jaanika Tamm’, age:55, sex:’F’})

>

> CREATE (Basket1:pasket {name:’Basket1′})

> CREATE (Basket2:pasket {name:’Basket2′})

> CREATE (Basket3:pasket {name:’Basket3′})

> CREATE (Basket4:pasket {name:’Basket4′})

> CREATE (Basket5:pasket {name:’Basket5′})

>

> CREATE (Item1:item {name:’Item1′, price:”34″, amount:2})

> CREATE (Item2:item {name:’Item2′, price:”3″, amount:1})

> CREATE (Item3:item {name:’Item3′, price:”4″, amount:3})

> CREATE (Item4:item {name:’Item4′, price:”64″, amount:5})

> CREATE (Item5:item {name:’Item5′, price:”88″, amount:2})

> CREATE (Item6:item {name:’Item6′, price:”32″, amount:1})

> CREATE (Item7:item {name:’Item7′, price:”74″, amount:20})

> CREATE (Item8:item {name:’Item8′, price:”1″, amount:2})

>

> CREATE (Client1)-[:OWN]->(Basket1)

> CREATE (Client1)-[:OWN]->(Basket2)

> CREATE (Client2)-[:OWN]->(Basket3)

> CREATE (Client3)-[:OWN]->(Basket4)

> CREATE (Client4)-[:OWN]->(Basket5)

>

> CREATE (Item1)-[:IN]->(Basket1)

> CREATE (Item2)-[:IN]->(Basket1)

> CREATE (Item3)-[:IN]->(Basket2)

> CREATE (Item4)-[:IN]->(Basket3)

> CREATE (Item5)-[:IN]->(Basket4)

> CREATE (Item6)-[:IN]->(Basket5)

> CREATE (Item7)-[:IN]->(Basket1)

> CREATE (Item7)-[:IN]->(Basket2)

> CREATE (Item7)-[:IN]->(Basket3)

> CREATE (Item7)-[:IN]->(Basket4)

> CREATE (Item7)-[:IN]->(Basket5)

> CREATE (Item8)-[:IN]->(Basket2)

> CREATE (Item8)-[:IN]->(Basket3)

> ;

Now you can visualize your data in different environments.

The easiest way is to use neo4j databrowser

Screen Shot 2014-01-29 at 11.20.10

 

or you can choose some  3th part application to play with your data. In example I use neoclipse

Screen Shot 2014-01-29 at 11.16.48

 

Now we have nodes and relations in db and we can visualize them.

Neo4j is more than tool for data visualization. It is database so we can make queries.

Why do we need queries if we have so nice graphical presentation. In case if we have huge amount of data the graphical presentation may be a little bit difficult to follow and patterns we are looking for my be not so easily found.

Lets see what interesting queries we can produce based on our existing data.

Lets take Item2 (NodeID: 10)

The easiest way to make queries for me is to use neo4j-shell.

Lets pretend we need to know who are buyers of current Item

neo4j-sh (Item2,10)$ MATCH (i {name:’Item2′})-[:IN]-b-[:OWN]-c RETURN i, b, c;

+—————————————————————————————————————-+

| i                                         | b                       | c                                        |

+—————————————————————————————————————-+

| Node[10]{name:”Item2″,price:”3″,amount:1} | Node[4]{name:”Basket1″} | Node[0]{name:”Ants Konn”,age:34,sex:”M”} |

+—————————————————————————————————————-+

1 row

We can see that Item2 is not very popular product. What about Item7?

neo4j-sh (?)$ MATCH (i {name:’Item7′})-[:IN]-b-[:OWN]-c RETURN i, b, c;

+———————————————————————————————————————+

| i                                           | b                       | c                                           |

+———————————————————————————————————————+

| Node[15]{name:”Item7″,price:”74″,amount:20} | Node[4]{name:”Basket1″} | Node[0]{name:”Ants Konn”,age:34,sex:”M”}    |

| Node[15]{name:”Item7″,price:”74″,amount:20} | Node[5]{name:”Basket2″} | Node[0]{name:”Ants Konn”,age:34,sex:”M”}    |

| Node[15]{name:”Item7″,price:”74″,amount:20} | Node[6]{name:”Basket3″} | Node[1]{name:”Ivan Orav”,age:66,sex:”M”}    |

| Node[15]{name:”Item7″,price:”74″,amount:20} | Node[7]{name:”Basket4″} | Node[2]{name:”Kadri Kala”,age:24,sex:”F”}   |

| Node[15]{name:”Item7″,price:”74″,amount:20} | Node[8]{name:”Basket5″} | Node[3]{name:”Jaanika Tamm”,age:55,sex:”F”} |

+———————————————————————————————————————+

5 rows

24 ms

We can see that Item7 is much popular product comparing with Item2.

So who are buyers bought Item7

neo4j-sh (?)$ MATCH (i {name:’Item7′})-[:IN]-b-[:OWN]-c RETURN DISTINCT c;

+———————————————+

| c                                           |

+———————————————+

| Node[0]{name:”Ants Konn”,age:34,sex:”M”}    |

| Node[1]{name:”Ivan Orav”,age:66,sex:”M”}    |

| Node[2]{name:”Kadri Kala”,age:24,sex:”F”}   |

| Node[3]{name:”Jaanika Tamm”,age:55,sex:”F”} |

+———————————————+

4 rows

37 ms

 

So very cool queries 🙂

Lets make thinks more interesting and create new relation between customers Ants Konn and Jaanika Tamm and pretend they are couple. Ignore lastnames 🙂

Screen Shot 2014-01-29 at 12.55.51

 

Now we can ask a question in example are there items bought by related persons?

neo4j-sh (?)$ MATCH i-[:IN]-b-[:OWN]-c-[]-c2-[OWN]-b2-[IN]-i RETURN DISTINCT c, i;

+——————————————————————————————-+

| c                                           | i                                           |

+——————————————————————————————-+

| Node[3]{name:”Jaanika Tamm”,age:55,sex:”F”} | Node[15]{name:”Item7″,price:”74″,amount:20} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”}    | Node[15]{name:”Item7″,price:”74″,amount:20} |

+——————————————————————————————-+

2 rows

29 ms

We found that Item7 is the only Item bought by that couple.

Lets make thinks more complicated and add one more relation between Ants Konn and Ivan Orav as father and son. Don’t lool surnames again 🙂 and put Item1 into basket3 as well.

Screen Shot 2014-01-29 at 13.17.18

 

Lets query now Items bought by related customers

neo4j-sh (?)$ MATCH i-[:IN]-b-[:OWN]-c-[]-c2-[OWN]-b2-[IN]-i RETURN DISTINCT c.name, i.name ORDER BY i.name;

+————————–+

| c.name         | i.name  |

+————————–+

| “Ivan Orav”    | “Item1” |

| “Ants Konn”    | “Item1” |

| “Jaanika Tamm” | “Item7” |

| “Ivan Orav”    | “Item7” |

| “Ants Konn”    | “Item7” |

| “Ivan Orav”    | “Item8” |

| “Ants Konn”    | “Item8” |

+————————–+

7 rows

100 ms

neo4j-sh (?)$

One example about query “my friends friends” that gives as all nodes after node we are connected

neo4j-sh (Ants Konn,0)$ start n=node:node_auto_index(name=’Ants Konn’) MATCH n–()–t RETURN n, t;

+—————————————————————————————-+

| n                                        | t                                           |

+—————————————————————————————-+

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[16]{name:”Item8″,price:”1″,amount:2}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[15]{name:”Item7″,price:”74″,amount:20} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[11]{name:”Item3″,price:”4″,amount:3}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[15]{name:”Item7″,price:”74″,amount:20} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[10]{name:”Item2″,price:”3″,amount:1}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[9]{name:”Item1″,price:”34″,amount:2}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[8]{name:”Basket5″}                     |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[6]{name:”Basket3″}                     |

+—————————————————————————————-+

8 rows

17 ms

and here we can add information about node we jumped over

neo4j-sh (Ants Konn,0)$ start n=node:node_auto_index(name=’Ants Konn’) MATCH n–(i)–t RETURN n, i, t;

+————————————————————————————————————————————–+

| n                                        | i                                           | t                                           |

+————————————————————————————————————————————–+

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[5]{name:”Basket2″}                     | Node[16]{name:”Item8″,price:”1″,amount:2}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[5]{name:”Basket2″}                     | Node[15]{name:”Item7″,price:”74″,amount:20} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[5]{name:”Basket2″}                     | Node[11]{name:”Item3″,price:”4″,amount:3}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[4]{name:”Basket1″}                     | Node[15]{name:”Item7″,price:”74″,amount:20} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[4]{name:”Basket1″}                     | Node[10]{name:”Item2″,price:”3″,amount:1}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[4]{name:”Basket1″}                     | Node[9]{name:”Item1″,price:”34″,amount:2}   |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[3]{name:”Jaanika Tamm”,age:55,sex:”F”} | Node[8]{name:”Basket5″}                     |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | Node[1]{name:”Ivan Orav”,age:66,sex:”M”}    | Node[6]{name:”Basket3″}                     |

+————————————————————————————————————————————–+

8 rows

16 ms

neo4j-sh (Ants Konn,0)$

Another query to get relations. So lets get all relations related with Ants Konn

neo4j-sh (Ants Konn,0)$ start n=node:node_auto_index(name=’Ants Konn’) MATCH n-[r]-t RETURN n, r;

+———————————————————–+

| n                                        | r              |

+———————————————————–+

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :OWN[1]{}      |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :OWN[0]{}      |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :HUSBAND[21]{} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :SON[22]{}     |

+———————————————————–+

4 rows

10 ms

neo4j-sh (Ants Konn,0)$

You can specify relation direction using “>” and “<“. Query relations that goes out from Ants Konn

neo4j-sh (Ants Konn,0)$ sto_index(name=’Ants Konn’) MATCH n-[r]->t RETURN n, r;

+———————————————————–+

| n                                        | r              |

+———————————————————–+

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :OWN[1]{}      |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :OWN[0]{}      |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :HUSBAND[21]{} |

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :SON[22]{}     |

+———————————————————–+

4 rows

6 ms

And query for incoming relations for Ants Konn

neo4j-sh (Ants Konn,0)$ start n=node:node_auto_index(name=’Ants Konn’) MATCH n<-[r]-t RETURN n, r;

+——-+

| n | r |

+——-+

+——-+

0 row

5 ms

So at the moment there are’t any incoming relation. Lets create one and lets query again.

Screen Shot 2014-01-29 at 14.51.35

 

As you see there is now one incoming relation for Ants Konn. Lets query

neo4j-sh (Ants Konn,0)$ start n=node:node_auto_index(name=’Ants Konn’) MATCH n<-[r]-t RETURN n, r;

+———————————————————-+

| n                                        | r             |

+———————————————————-+

| Node[0]{name:”Ants Konn”,age:34,sex:”M”} | :FRIEND[24]{} |

+———————————————————-+

1 row

5 ms

neo4j-sh (Ants Konn,0)$

So Ants Konn is not so lonely any more he has one friend 🙂

One more nice picture about our relations using neo4j web tools

Screen Shot 2014-01-29 at 15.35.20

Sow that was a light introduction about some possibilities of neo4j.

neo4j and Cypher Query Language

Andmestruktuur

neo4j_data

 

Võtame kõik ahelad, mis on toodete vahel (läbi ostude) e kahe ostulised ahelad.

Meil on kolm kahe ostulist ahelat – punane (42 -> 43), sinine (42 ->43) ja rohelin (43 -> 48)

neo4j_data_ahelad

 


neo4j-sh (23,40)$ START a=node(*) MATCH a<-[:RELATED_TO]-(b)-[:FOLLOWED_TO]->(c)-[:RELATED_TO]-(d) RETURN a, d;
+-----------------------------------------------------------------------------+
| a | d |
+-----------------------------------------------------------------------------+
| Node[42] | Node[43] |
| Node[42] | Node[43] |
| Node[43] | Node[48] |
+-----------------------------------------------------------------------------+
3 rows

Saame kolm teekonda.

Unikaalsed teekonnad:

neo4j-sh (23,40)$ START a=node(*) MATCH a<-[:RELATED_TO]-(b)-[:FOLLOWED_TO]->(c)-[:RELATED_TO]-(d) RETURN DISTINCT a, d;
+—————————————————————————–+
| a | d |
+—————————————————————————–+
| Node[42] | Node[43] |
| Node[43] | Node[48] |
+—————————————————————————–+
2 rows

Loendame teekonnad:

neo4j-sh (EE-EE000023,40)$ START a=node(*) MATCH a<-[:RELATED_TO]-(b)-[:FOLLOWED_TO]->(c)-[:RELATED_TO]-(d) RETURN DISTINCT a, d, COUNT(a);
+—————————————————————————————-+
| a | d | COUNT(a) |
+—————————————————————————————-+
| Node[43]} |  | 1 |
| Node[42] | Node[43] | 2 |
+—————————————————————————————-+
2 rows

Kolme ostuline ahel.

neo4j_data_ahelad_3mene

 

neo4j-sh (23,40)$ START a=node(*) MATCH a<-[:RELATED_TO]-(b)-[:FOLLOWED_TO*2]->(c)-[:RELATED_TO]-(d) RETURN DISTINCT a, d, COUNT(a);

+————————————————————————————–+
| a | d | COUNT(a) |
+————————————————————————————–+
| Node[42] | Node[48] | 1 |
+————————————————————————————–+
1 row