1
votes

Beginning with Neo4j 1.9.2, and using Cypher query language, I would like to create relationships between nodes having a specific property value in common. I have set of nodes G having a property H, without any relationship currently existing between G nodes.

In a Cypher statement, is it possible to group G nodes by H property value and create a relationship HR between each nodes becoming to same group? Knowing that each group have a size between 2 & 10 and I'm having more than 15k of such groups (15k different H values) for about 50k G nodes.

I've tried hard to manage such query without finding a correct syntax. Below is a small sample dataset:

create 
(G1 {name:'G1', H:'1'}),
(G2 {name:'G2', H:'1'}),
(G3 {name:'G3', H:'1'}),

(G4 {name:'G4', H:'2'}),
(G5 {name:'G5', H:'2'}),
(G6 {name:'G6', H:'2'}),
(G7 {name:'G7', H:'2'})
return * ;

At the end, I'd like such relationships:

G1-[:HR]-G2-[:HR]-G3-[:HR]-G1

And:

G4-[:HR]-G5-[:HR]-G6-[:HR]-G7-[:HR]-G4

In another case, I may want to update massively the relationships between nodes using/comparing some of their properties. Imagine nodes of type N and nodes of type M, with N nodes related to M with a relationship named :IS_LOCATED_ON. The order of the location can be stored as a property of N nodes (N.relativePosition being Long from 1 to MAX_POSITION), but we may need later to update the graph model such a way: make N nodes linked between themselves by a new :PRECEDES relationship, so that we can find easier and faster next node N on the given set.

I'd expect such language may allow to update massive set of nodes/relationships manipulating their properties.

  • Is it not possible?
  • If not, is it planned or may be it planned?

Any help would be greatly appreciated.

2

2 Answers

2
votes

Since there's nothing in the data you supplied to get rank, I've played with collections to get one as follows:

START 
    n=node(*), n2=node(*) 
WHERE 
    HAS(n.H) AND HAS(n2.H) AND n.H = n2.H
WITH n, n2 ORDER BY n2.name
WITH n, COLLECT(n2) as others
WITH n, others, LENGTH(FILTER(x IN others : x.name < n.name)) as rank
RETURN n.name, n.H, rank ORDER BY n.H, n.name;

Building off of that you can then start determining relationships

START 
    n=node(*), n2=node(*) 
WHERE 
    HAS(n.H) AND HAS(n2.H) AND n.H = n2.H
WITH n, n2 ORDER BY n2.name
WITH n, COLLECT(n2) as others
WITH n, others, LENGTH(FILTER(x IN others : x.name < n.name)) as rank
WITH n, others, rank, COALESCE(
    HEAD(FILTER(x IN others : x.name > n.name)),
    HEAD(others)
    ) as next
RETURN n.name, n.H, rank, next ORDER BY n.H, n.name;

Finally ( and slightly more condensed )

START 
    n=node(*), n2=node(*) 
WHERE 
    HAS(n.H) AND HAS(n2.H) AND n.H = n2.H
WITH n, n2 ORDER BY n2.name
WITH n, COLLECT(n2) as others
WITH n, others, COALESCE(
    HEAD(FILTER(x IN others : x.name > n.name)),
    HEAD(others)
    ) as next
CREATE n-[:HR]->next
RETURN n, next;
0
votes

You can just do it like that, maybe indicate direction in your relationships:

CREATE 
  (G1 { name:'G1', H:'1' }),
  (G2 { name:'G2', H:'1' }),
  (G3 { name:'G3', H:'1' }),
  (G4 { name:'G4', H:'2' }),
  (G5 { name:'G5', H:'2' }),
  (G6 { name:'G6', H:'2' }),
  (G7 { name:'G7', H:'2' }), 
  G1-[:HR]->G2-[:HR]->G3-[:HR]->G1, 
  G4-[:HR]->G5-[:HR]->G6-[:HR]->G7-[:HR]->G1

See http://console.neo4j.org/?id=ujns0x for an example.