ryoakg
3/30/2017 - 11:21 AM

labels-vs-indexed-properties.cypher

// via: http://graphaware.com/neo4j/2015/01/16/neo4j-graph-model-design-labels-versus-indexed-properties.html

// setup the graph
FOREACH (n IN range(0,9) | MERGE (:User {id: n}));
FOREACH (n IN range(0,199) | MERGE (:BlogPost {id: n, body: 'abc'}));
FOREACH (n IN range(0,199) | MERGE (:BlogPost:ActivePost {id: n+200, body: 'abc', active: true}));

UNWIND range(0,399) AS n
MATCH (u:User {id: n%10}), (p:BlogPost {id: n})
MERGE (u)-[:WRITTEN]->(p);

// 1. Retrieving active blog posts
PROFILE MATCH (post:ActivePost) RETURN count(post);

PROFILE MATCH (post:BlogPost) WHERE post.active = true RETURN count(post);
// make the property indexed and try again
CREATE INDEX ON :BlogPost(active);
PROFILE MATCH (post:BlogPost) WHERE post.active = true RETURN count(post);

// 2. Retrieving active blog posts written by a user
PROFILE MATCH (user:User {id:1})
WITH user
MATCH (user)-[:WRITTEN]->(p:ActivePost)
RETURN count(p);

PROFILE MATCH (user:User {id:1})
WITH user
MATCH (user)-[:WRITTEN]->(p:BlogPost)
WHERE p.active = true
RETURN count(p);

// 3. Always use dedicated labels for positives
PROFILE MATCH (user:User {id:1})
WITH user
MATCH (user)-[:WRITTEN]->(p:BlogPost)
WHERE NOT p :Draft
RETURN count(p);

// 4. Avoid the need to match on multiple labels
PROFILE MATCH (post:BlogPost:ActivePost)
RETURN count(post);

// 5. Use well named relationship types to avoid some use of labels
MATCH (n:ActivePost)
WITH n
MATCH (n)<-[:WRITTEN]-(u)
MERGE (u)-[:PUBLISHED]->(n);

MATCH (n:BlogPost)
WHERE NOT n :ActivePost
WITH n
MATCH (n)<-[:WRITTEN]-(u)
MERGE (u)-[:DRAFTED]->(n);

PROFILE MATCH (user:User {id:1})
WITH user
MATCH (user)-[:PUBLISHED]->(p)
RETURN count(p);

// tear down
MATCH ()-[a:DRAFTED]->() DELETE a;
MATCH ()-[a:PUBLISHED]->() DELETE a;
MATCH ()-[a:WRITTEN]->() DELETE a;
MATCH (a:User) DELETE a;
MATCH (a:BlogPost) DELETE a;
MATCH (a:ActivePost) DELETE a;
DROP INDEX ON :BlogPost(active);