Slide 1

Slide 1 text

Extensibility for Java Developers in Neo4j Jennifer Reif Neo4j @JMHReif

Slide 2

Slide 2 text

Software Engineer, Neo4j - Developer - Blogger - Conference speaker - Continuous learner Hobbies: cats, coffee, and traveling :) [email protected] @JMHReif Who Am I?

Slide 3

Slide 3 text

What is a Graph Database?

Slide 4

Slide 4 text

Chart Graph

Slide 5

Slide 5 text

Database - specifically graph • Database: a structured set of data held in a computer, especially one that is accessible in various ways. • Relational? NoSQL? Graph? • Graph database: uses graph structures for semantic queries with nodes, edges and properties to represent and store data.

Slide 6

Slide 6 text

Neo4j is a Graph Database

Slide 7

Slide 7 text

Neo4j Fast Reliable No size limit Binary & HTTP protocol ACID transactions 2-4 M
 ops/s per core Clustering scale & HA Official Drivers Neo4j is a database

Slide 8

Slide 8 text

Neo4j Native GraphDB Cypher Query Language Developer Workbench Extensible Procedures & Functions Schema Free Property Graph Model Graph Visualization Graph Storage Neo4j is a graph database

Slide 9

Slide 9 text

Neo4j Developer Surface Native LanguageDrivers BOLT User- Defined Procedure 2000-2010 0.x Embedded Java API 2010-2014 1.x REST 2014-2015 2.x Cypher over HTTP 2016 3.0.x Bolt, Official Language Drivers, User-Defined Procedures 2016 3.1.x User-Defined Functions 2017 3.2.x User-Defined Aggregation Functions

Slide 10

Slide 10 text

Neo4j Developer Surface Native LanguageDrivers BOLT User- Defined Procedure 2000-2010 0.x Embedded Java API 2010-2014 1.x REST 2014-2015 2.x Cypher over HTTP 2016 3.0.x Bolt, Official Language Drivers, User Defined Procedures 2016 3.1.x User Defined Functions 2017 3.2.x User Defined Aggregation Functions

Slide 11

Slide 11 text

Interfaces to Neo4j • BOLT: • binary protocol / Cypher-only pipe • type system similar to Cypher • official drivers • HTTP: • familiar protocol • JSON (lossy) • community drivers / standard HTTP tooling • Embedded: • Java-only • core API • in-process

Slide 12

Slide 12 text

Bolt Binary Protocol • High-performance protocol • Secure transport (auth/TLS) • Shared connections (pooling) • More inclusive data type system • Procedure functionality

Slide 13

Slide 13 text

Neo4j Bolt Drivers

Slide 14

Slide 14 text

Official Drivers

Slide 15

Slide 15 text

Java Driver import org.neo4j.driver.v1.*; Driver driver = GraphDatabase.driver( "bolt://localhost", AuthTokens.basic( "neo4j", "neo4j" ) ); Session session = driver.session(); session.run( "CREATE (a:Person {name:'Arthur', title:'King'})" ); StatementResult result = session.run( "MATCH (a:Person) WHERE a.name = 'Arthur' RETURN a.name AS name, a.title AS title" ); while ( result.hasNext() ) { Record record = result.next(); System.out.println( record.get( "title" ).asString() + " " + record.get("name").asString() ); } session.close(); driver.close(); github.com/neo4j/neo4j-java-driver / org.neo4j.driver:neo4j-java-driver:1.5.0

Slide 16

Slide 16 text

Javascript Driver var neo4j = require('neo4j-driver').v1; var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j")); var session = driver.session(); session .run( "CREATE (a:Person {name:'Arthur', title:'King'})" ) .then( function() { return session.run( "MATCH (a:Person) WHERE a.name = 'Arthur' RETURN a.name AS name, a.title AS title" ) }) .then( function( result ) { console.log( result.records[0].get("title") + " " + result.records[0].get("name") ); session.close(); driver.close(); }) github.com/neo4j/neo4j-javascript-driver / npm install neo4j-driver

Slide 17

Slide 17 text

Python Driver from neo4j.v1 import GraphDatabase, basic_auth driver = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "neo4j")) session = driver.session() session.run("CREATE (a:Person {name:'Arthur', title:'King'})") query = "MATCH (a:Person) WHERE a.name = 'Arthur' RETURN a.name AS name, a.title AS title" result = session.run(query) for record in result: print("%s %s" % (record["title"], record["name"])) session.close() github.com/neo4j/neo4j-python-driver / pip install neo4j-driver

Slide 18

Slide 18 text

.NET Driver using Neo4j.Driver.V1; using (var driver = GraphDatabase.Driver("bolt://localhost", AuthTokens.Basic("neo4j", "neo4j"))) using (var session = driver.Session()) { session.Run("CREATE (a:Person {name:'Arthur', title:'King'})"); var result = session.Run("MATCH (a:Person) WHERE a.name = 'Arthur' RETURN a.name AS name, a.title AS title"); foreach (var record in result) { Output.WriteLine($"{record["title"].As()} {record["name"].As()}"); } } github.com/neo4j/neo4j-dotnet-driver / PM> Install-Package Neo4j.Driver-1.0.3

Slide 19

Slide 19 text

Community Drivers

Slide 20

Slide 20 text

Spring Data Neo4j & Object-Graph Mapper

Slide 21

Slide 21 text

https://projects.spring.io/spring-data-neo4j/

Slide 22

Slide 22 text

https://github.com/spring-projects/spring-data-neo4j

Slide 23

Slide 23 text

Capabilities • Can use with SpringBoot • Annotation-based OGM for POJOs • Connect to Neo4j with Bolt, HTTP, and embedded • Interface-based repository support • Persistence lifecycle events

Slide 24

Slide 24 text

@NodeEntity public class Person { @Id @GeneratedValue private Long id; private String name; private int born; @Relationship(type = "ACTED_IN") private List movies = new ArrayList<>(); } @NodeEntity public class Movie { … @JsonIgnoreProperties("movie") @Relationship(type = "ACTED_IN", direction = Relationship.INCOMING) private List roles; } @RelationshipEntity(type = "ACTED_IN") public class Role { @Id @GeneratedValue private Long id; private List roles = new ArrayList<>(); @StartNode private Person person; @EndNode private Movie movie; }

Slide 25

Slide 25 text

public interface MovieRepository extends Neo4jRepository { //derived finder methods - auto-mapping Movie findByTitle(@Param("title") String title); Collection findByTitleLike(@Param("title") String title); @Query("MATCH (m:Movie)<-[r:ACTED_IN]-(a:Person) RETURN m,r,a LIMIT {limit}") Collection graph(@Param("limit") int limit); }

Slide 26

Slide 26 text

@Service public class MovieService { private final MovieRepository movieRepository; public MovieService(MovieRepository movieRepository) { this.movieRepository = movieRepository; } @Transactional(readOnly = true) public Movie findByTitle(String title) { return movieRepository.findByTitle(title); } @Transactional(readOnly = true) public Collection findByTitleLike(String title) { return movieRepository.findByTitleLike(title); } @Transactional(readOnly = true) public Map graph(int limit) { Collection result = movieRepository.graph(limit); return toD3Format(result); } } https://neo4j.com/developer/spring-data-neo4j/

Slide 27

Slide 27 text

Neo4j Developer Surface Native LanguageDrivers BOLT User- Defined Procedure 2000-2010 0.x Embedded Java API 2010-2014 1.x REST 2014-2015 2.x Cypher over HTTP 2016 3.0.x Bolt, Official Language Drivers, User-Defined Procedures 2016 3.1.x User-Defined Functions 2017 3.2.x User-Defined Aggregation Functions

Slide 28

Slide 28 text

Procedures Functions Aggregate Functions

Slide 29

Slide 29 text

Can be written in any JVM language

Slide 30

Slide 30 text

User-Defined Procedures

Slide 31

Slide 31 text

Callable as Stand-Alone or in Cypher Statements

Slide 32

Slide 32 text

CALL example.search('User','name:Brook*')

Slide 33

Slide 33 text

public class FullTextIndex { @Context public GraphDatabaseService db; @Procedure( name = "example.search", mode = Procedure.Mode.READ ) public Stream search( @Name("index") String index, 
 @Name("query") String query ) { if( !db.index().existsForNodes( index )) { return Stream.empty(); } return db.index().forNodes( index ).query( query ).stream()
 .map( SearchHit::new ); } public static class SearchHit { public final Node node; SearchHit(Node node) { this.node = node; } } }

Slide 34

Slide 34 text

public class FullTextIndex { @Context public GraphDatabaseService db; @Procedure( name = "example.search", mode = Procedure.Mode.READ ) public Stream search( @Name("index") String index, 
 @Name("query") String query ) { if( !db.index().existsForNodes( index )) { return Stream.empty(); } return db.index().forNodes( index ).query( query ).stream()
 .map( SearchHit::new ); } public static class SearchHit { public final Node node; SearchHit(Node node) { this.node = node; } } }

Slide 35

Slide 35 text

public class FullTextIndex { @Context public GraphDatabaseService db; @Procedure( name = "example.search", mode = Procedure.Mode.READ ) public Stream search( @Name("index") String index, 
 @Name("query") String query ) { if( !db.index().existsForNodes( index )) { return Stream.empty(); } return db.index().forNodes( index ).query( query ).stream()
 .map( SearchHit::new ); } public static class SearchHit { public final Node node; SearchHit(Node node) { this.node = node; } } }

Slide 36

Slide 36 text

try ( Driver driver = GraphDatabase.driver("bolt://localhost", Config.build().toConfig()) ) { try ( Session session = driver.session() ) { String call = "CALL example.search('User',$query)"; Map params = singletonMap("query", "name:Brook*"); StatementResult result = session.run(call, params); while ( result.hasNext() ) { // process results } } }

Slide 37

Slide 37 text

try ( Driver driver = GraphDatabase.driver("bolt://localhost", Config.build().toConfig()) ) { try ( Session session = driver.session() ) { String call = "CALL example.search('User',$query)"; Map params = singletonMap("query", "name:Brook*"); StatementResult result = session.run(call, params); while ( result.hasNext() ) { // process results } } }

Slide 38

Slide 38 text

User-Defined Functions

Slide 39

Slide 39 text

Useable in any Cypher expression or lightweight computation

Slide 40

Slide 40 text

RETURN example.join(['Hello','World'],' ') => "Hello World"

Slide 41

Slide 41 text

public class Join { @UserFunction @Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.") public String join( @Name(“strings") List strings, @Name(value = "delimiter", defaultValue = ",") String delimiter) { if ( strings == null || delimiter == null ) { return null; } return String.join( delimiter, strings ); } }

Slide 42

Slide 42 text

public class Join { @UserFunction @Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.") public String join( @Name("strings") List strings, @Name(value = "delimiter", defaultValue = ",") String delimiter) { if ( strings == null || delimiter == null ) { return null; } return String.join( delimiter, strings ); } }

Slide 43

Slide 43 text

public class Join { @UserFunction @Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.") public String join( @Name("strings") List strings, @Name(value = "delimiter", defaultValue = ",") String delimiter) { if ( strings == null || delimiter == null ) { return null; } return String.join( delimiter, strings ); } }

Slide 44

Slide 44 text

try ( Driver driver = GraphDatabase.driver( "bolt://localhost", 
 Config.build().toConfig() ) ) { try ( Session session = driver.session() ) { String query = "RETURN example.join(['Hello','World']) AS result"; String result = session.run( query ) .single().get( "result" ).asString(); } }

Slide 45

Slide 45 text

User-Defined Aggregation Functions

Slide 46

Slide 46 text

Custom, efficient aggregations for Data Science and BI

Slide 47

Slide 47 text

UNWIND ['abc', 'abcd', 'ab'] AS string
 RETURN example.longestString(string) => 'abcd'

Slide 48

Slide 48 text

public class LongestString { @UserAggregationFunction @Description( "aggregates the longest string found" ) public LongStringAggregator longestString() { return new LongStringAggregator(); } public static class LongStringAggregator { private int longest; private String longestString; @UserAggregationUpdate public void findLongest( @Name( "string" ) String string ) { if ( string != null && string.length() > longest) { longest = string.length(); longestString = string; } } @UserAggregationResult public String result() { return longestString; } } }

Slide 49

Slide 49 text

public class LongestString { @UserAggregationFunction @Description( "aggregates the longest string found" ) public LongStringAggregator longestString() { return new LongStringAggregator(); } public static class LongStringAggregator { private int longest; private String longestString; @UserAggregationUpdate public void findLongest( @Name( "string" ) String string ) { if ( string != null && string.length() > longest) { longest = string.length(); longestString = string; } } @UserAggregationResult public String result() { return longestString; } } }

Slide 50

Slide 50 text

public class LongestString { @UserAggregationFunction @Description( "aggregates the longest string found" ) public LongStringAggregator longestString() { return new LongStringAggregator(); } public static class LongStringAggregator { private int longest; private String longestString; @UserAggregationUpdate public void findLongest( @Name( "string" ) String string ) { if ( string != null && string.length() > longest) { longest = string.length(); longestString = string; } } @UserAggregationResult public String result() { return longestString; } } }

Slide 51

Slide 51 text

public class LongestString { @UserAggregationFunction @Description( "aggregates the longest string found" ) public LongStringAggregator longestString() { return new LongStringAggregator(); } public static class LongStringAggregator { private int longest; private String longestString; @UserAggregationUpdate public void findLongest( @Name( "string" ) String string ) { if ( string != null && string.length() > longest) { longest = string.length(); longestString = string; } } @UserAggregationResult public String result() { return longestString; } } }

Slide 52

Slide 52 text

try ( Driver driver = GraphDatabase.driver("bolt://localhost", 
 Config.build().toConfig()) ) { try ( Session session = driver.session() ) { String query = "UNWIND ['abc', 'abcd', 'ab'] AS string " + "RETURN example.longestString(string) AS result"; String result = session.run(query).single().get("result").asString(); } }

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

Awesome Procedures On Cypher

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

450+ procedures and functions

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

APOC - Data Integration

Slide 60

Slide 60 text

Load from a relational database

Slide 61

Slide 61 text

apoc.load.jdbc WITH "jdbc:mysql://localhost:3306/northwind?user=root" AS url CALL apoc.load.jdbc(url,"products") 
 YIELD row MERGE (p:Product {id: row.ProductID}) SET p.name = row.ProductName, p.unitPrice = row.UnitPrice

Slide 62

Slide 62 text

WITH "jdbc:mysql://localhost:3306/northwind?user=root" AS url CALL apoc.load.jdbc(url,"products") 
 YIELD row MERGE (p:Product {id: row.ProductID}) SET p.name = row.ProductName, p.unitPrice = row.UnitPrice Execute procedure

Slide 63

Slide 63 text

Apply Cypher transformation WITH "jdbc:mysql://localhost:3306/northwind?user=root" AS url CALL apoc.load.jdbc(url,"products") 
 YIELD row MERGE (p:Product {id: row.ProductID}) SET p.name = row.ProductName, p.unitPrice = row.UnitPrice

Slide 64

Slide 64 text

Load XML

Slide 65

Slide 65 text

apoc.load.xml CALL apoc.load.xml('http://overpass.osm.rambler.ru/cgi/xapi_meta *[bbox=11.54,48.14,11.543,48.145]') YIELD value UNWIND value["_children"] AS child WITH child WHERE child["_type"] = "node" WITH child.id AS id, 
 child.lat AS latitude, 
 child.lon AS longitude, 
 child["user"] AS userName MERGE (point:Point {id: id}) SET point.latitude = latitude, 
 point.longitude = longitude MERGE (user:User {name: userName}) MERGE (user)-[:EDITED]->(point)

Slide 66

Slide 66 text

Execute procedure CALL apoc.load.xml('http://overpass.osm.rambler.ru/cgi/xapi_meta? *[bbox=11.54,48.14,11.543,48.145]') YIELD value UNWIND value["_children"] AS child WITH child WHERE child["_type"] = "node" WITH child.id AS id, 
 child.lat AS latitude, 
 child.lon AS longitude, 
 child["user"] AS userName MERGE (point:Point {id: id}) SET point.latitude = latitude, 
 point.longitude = longitude MERGE (user:User {name: userName}) MERGE (user)-[:EDITED]->(point)

Slide 67

Slide 67 text

UNWIND the array of elements CALL apoc.load.xml('http://overpass.osm.rambler.ru/cgi/xapi_meta? *[bbox=11.54,48.14,11.543,48.145]') YIELD value UNWIND value["_children"] AS child WITH child WHERE child["_type"] = "node" WITH child.id AS id, 
 child.lat AS latitude, 
 child.lon AS longitude, 
 child["user"] AS userName MERGE (point:Point {id: id}) SET point.latitude = latitude, 
 point.longitude = longitude MERGE (user:User {name: userName}) MERGE (user)-[:EDITED]->(point)

Slide 68

Slide 68 text

Filter rows CALL apoc.load.xml('http://overpass.osm.rambler.ru/cgi/xapi_meta? *[bbox=11.54,48.14,11.543,48.145]') YIELD value UNWIND value["_children"] AS child WITH child WHERE child["_type"] = "node" WITH child.id AS id, 
 child.lat AS latitude, 
 child.lon AS longitude, 
 child["user"] AS userName MERGE (point:Point {id: id}) SET point.latitude = latitude, 
 point.longitude = longitude MERGE (user:User {name: userName}) MERGE (user)-[:EDITED]->(point)

Slide 69

Slide 69 text

Apply Cypher transformation CALL apoc.load.xml('http://overpass.osm.rambler.ru/cgi/xapi_meta? *[bbox=11.54,48.14,11.543,48.145]') YIELD value UNWIND value["_children"] AS child WITH child WHERE child["_type"] = "node" WITH child.id AS id, 
 child.lat AS latitude, 
 child.lon AS longitude, 
 child["user"] AS userName MERGE (point:Point {id: id}) SET point.latitude = latitude, 
 point.longitude = longitude MERGE (user:User {name: userName}) MERGE (user)-[:EDITED]->(point)

Slide 70

Slide 70 text

Load JSON

Slide 71

Slide 71 text

apoc.load.json WITH "https://api.stackexchange.com/2.2/questions? pagesize=100&order=desc&sort=creation&tagged=neo4j&site=stackoverflow&filter=!5-i6Zw8Y)4W7vpy91PMYsKM- k9yzEsSC1_Uxlf" AS url CALL apoc.load.json(url) YIELD value UNWIND value.items AS q MERGE (question:Question {id:q.question_id}) 
 ON CREATE SET question.title = q.title, 
 question.share_link = q.share_link, 
 question.favorite_count = q.favorite_count MERGE (owner:User {id:q.owner.user_id}) 
 ON CREATE SET owner.display_name = q.owner.display_name
 MERGE (owner)-[:ASKED]->(question) FOREACH (tagName IN q.tags | 
 MERGE (tag:Tag {name:tagName}) MERGE (question)-[:TAGGED]->(tag))
 FOREACH (a IN q.answers | MERGE (question)<-[:ANSWERS]-(answer:Answer {id:a.answer_id}) MERGE (answerer:User {id:a.owner.user_id}) 
 ON CREATE SET answerer.display_name = a.owner.display_name 
 MERGE (answer)<-[:PROVIDED]-(answerer))

Slide 72

Slide 72 text

WITH "https://api.stackexchange.com/2.2/questions?pagesize=100&order=desc&sort=creation&tagged=neo4j&site=stackoverflow&filter=!5- i6Zw8Y)4W7vpy91PMYsKM-k9yzEsSC1_Uxlf" AS url CALL apoc.load.json(url) YIELD value UNWIND value.items AS q MERGE (question:Question {id:q.question_id}) 
 ON CREATE SET question.title = q.title, 
 question.share_link = q.share_link, 
 question.favorite_count = q.favorite_count MERGE (owner:User {id:q.owner.user_id}) 
 ON CREATE SET owner.display_name = q.owner.display_name
 MERGE (owner)-[:ASKED]->(question) FOREACH (tagName IN q.tags | 
 MERGE (tag:Tag {name:tagName}) MERGE (question)-[:TAGGED]->(tag))
 FOREACH (a IN q.answers | MERGE (question)<-[:ANSWERS]-(answer:Answer {id:a.answer_id}) MERGE (answerer:User {id:a.owner.user_id}) 
 ON CREATE SET answerer.display_name = a.owner.display_name 
 MERGE (answer)<-[:PROVIDED]-(answerer)) Use FOREACH for arrays within a row

Slide 73

Slide 73 text

APOC - Graph Refactoring

Slide 74

Slide 74 text

apoc.refactor.mergeNodes MATCH (n:Person) WITH n.email AS email, collect(n) as people WHERE size(people) > 1 CALL apoc.refactor.mergeNodes(people) YIELD node RETURN node

Slide 75

Slide 75 text

apoc.refactor.mergeNodes MATCH (n:Person) WITH n.email AS email, collect(n) as people WHERE size(people) > 1 CALL apoc.refactor.mergeNodes(people) YIELD node RETURN node

Slide 76

Slide 76 text

apoc.create.addLabels MATCH (n:Movie) CALL apoc.create.addLabels(id(n), [n.genre]) YIELD node REMOVE node.genre RETURN node

Slide 77

Slide 77 text

apoc.create.addLabels MATCH (n:Movie) CALL apoc.create.addLabels( id(n), [ n.genre ] ) YIELD node REMOVE node.genre RETURN node

Slide 78

Slide 78 text

APOC - Cypher Execution

Slide 79

Slide 79 text

Run large scale updates CALL apoc.periodic.iterate( 'MATCH (n:Person) RETURN n', 'SET n.name = n.firstName + " " + n.lastName',
 {batchSize:10000, parallel:true})

Slide 80

Slide 80 text

APOC - Utility Functions

Slide 81

Slide 81 text

Compute soundex encoding of a string CALL apoc.text.phonetic('Hello, dear User!') YIELD value RETURN value 
 // will return 'H436'

Slide 82

Slide 82 text

How similar do two strings sound? CALL apoc.text.phoneticDelta(
 'Hello Mr Rabbit', 'Hello Mr Ribbit') 
 // will return '4' (very similar)

Slide 83

Slide 83 text

Extract domain names WITH 'http://www.example.com/all-the-things' AS url RETURN apoc.data.domain(url) // will return 'www.example.com'

Slide 84

Slide 84 text

Date to Timestamp RETURN apoc.date.parse(
 '2015/03/25 03:15:59',
 's', 
 'yyyy/MM/dd HH:mm:ss'
 )
 
 // will return 1427253359

Slide 85

Slide 85 text

Timestamp to Date RETURN apoc.date.format(
 1427253359, 
 's', 
 'yyyy/MM/dd HH:mm:ss'
 ) 
 // will return "2015/03/25 03:15:59"

Slide 86

Slide 86 text

And many more! https://neo4j-contrib.github.io/neo4j-apoc-procedures/

Slide 87

Slide 87 text

Kafka and Neo4j

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

Functionality • Still in development! • Stream transaction event handler events to a Kafka topic • Read Kafka records from given topic(s) • Treat records as input parameters • Uses configured Cypher statements to merge into the graph

Slide 90

Slide 90 text

What Do I Need? • Configuration properties • Set up node-patterns to send to Kafka • Choose Labels and properties to include/exclude • Patterns separated by semicolon

Slide 91

Slide 91 text

neo4j.conf kafka.zookeeper.connect=localhost:2181 kafka.bootstrap.servers=localhost:9092 kafka.acks=1 kafka.num.partitions=1 kafka.retries=2 kafka.batch.size=16384 kafka.buffer.memory=33554432 kafka.reindex.batch.size=1000 kafka.session.timeout.ms=15000 kafka.connection.timeout.ms=10000 kafka.replication=1 kafka.group.id=neo4j kafka.topics=neo4j kafka.patterns=neo4j:*

Slide 92

Slide 92 text

Label & Property Setup kafka.topics=topic1,topic2 kafka.patterns=topic1:*;topic2:Label1 {prop1, prop2}, topic1:Label1:Label2{*,-prop1}, topic2:Label3{-prop1,-prop2,prop3}

Slide 93

Slide 93 text

RDF data into Neo4j

Slide 94

Slide 94 text

No content

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

Import RDF triples

Slide 97

Slide 97 text

semantics.importRDF CALL semantics.importRDF("file:///industry.ntriples","N-Triples", {})

Slide 98

Slide 98 text

Thomson Reuters' OpenPermID Graph

Slide 99

Slide 99 text

Graph-Aided Search

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

No content

Slide 102

Slide 102 text

No content

Slide 103

Slide 103 text

conf/neo4j.conf com.graphaware.runtime.enabled=true
 
 #ES becomes the module ID:
 com.graphaware.module.ES. 2=com.graphaware.module.es.ElasticSearchModuleBootstrapper
 
 #URI of Elasticsearch
 com.graphaware.module.ES.uri=localhost
 
 #Port of Elasticsearch
 com.graphaware.module.ES.port=9201

Slide 104

Slide 104 text

Find nodes CALL ga.es.queryNode(‘{\"query\": {\"match\":{\"name\":=\"alessandro\"}}}') YIELD node, score RETURN node, score

Slide 105

Slide 105 text

Find relationships CALL ga.es.queryRelationship(‘{\"query\": {\"match\":{\"city\":\"paris\"}}}') YIELD relationship, score RETURN relationship, score

Slide 106

Slide 106 text

dzone.com/refcardz/graph-powered-search-neo4j-amp-elasticsearch

Slide 107

Slide 107 text

Versioned Graphs

Slide 108

Slide 108 text

No content

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

Create node CALL graph.versioner.init('Person', 
 {ssn: 123456789, name: 'Marco'}, 
 {address: 'Via Roma 11'}
 )

Slide 111

Slide 111 text

Immutable properties CALL graph.versioner.init('Person', 
 {ssn: 123456789, name: 'Marco'}, 
 {address: 'Via Roma 11'}
 )

Slide 112

Slide 112 text

State properties CALL graph.versioner.init('Person', 
 {ssn: 123456789, name: 'Marco'}, 
 {address: 'Via Roma 11'}
 )

Slide 113

Slide 113 text

Update state MATCH (p:Person {name: "Marco"}) WITH p CALL graph.versioner.update(p, {address: 'Via Roma 12'}) YIELD node RETURN node

Slide 114

Slide 114 text

Pass in the new state MATCH (p:Person {name: "Marco"}) WITH p CALL graph.versioner.update(p, {address: 'Via Roma 12'}) YIELD node RETURN node

Slide 115

Slide 115 text

Spatial

Slide 116

Slide 116 text

No content

Slide 117

Slide 117 text

Create spatial index CALL spatial.addWKTLayer('geom', 'wkt')

Slide 118

Slide 118 text

Add spatial property to nodes CREATE (d:District {...}) SET d.wkt = 'MULTIPOLYGON(((23.22, ... )))'

Slide 119

Slide 119 text

Add nodes to spatial index MATCH (d:District) WITH collect(d) AS districts CALL spatial.addNodes('geom', districts) YIELD node RETURN count(*)

Slide 120

Slide 120 text

Query nodes by location CALL spatial.withinDistance('geom',
 {latitude: 37.563440, longitude: -122.322265}, 1) 
 YIELD node AS d WITH d, d.wkt AS wkt, d.state AS state, d.district AS district LIMIT 1 MATCH (d)<-[:REPRESENTS]-(l:Legislator) MATCH (l)-[:SERVES_ON]->(c:Committee) MATCH (c)<-[:REFERRED_TO]-(b:Bill) MATCH (b)-[:DEALS_WITH]->(s:Subject) RETURN *

Slide 121

Slide 121 text

Finds nodes within 1km CALL spatial.withinDistance('geom',
 {latitude: 37.563440, longitude: -122.322265}, 1) 
 YIELD node AS d WITH d, d.wkt AS wkt, d.state AS state, d.district AS district LIMIT 1 MATCH (d)<-[:REPRESENTS]-(l:Legislator) MATCH (l)-[:SERVES_ON]->(c:Committee) MATCH (c)<-[:REFERRED_TO]-(b:Bill) MATCH (b)-[:DEALS_WITH]->(s:Subject) RETURN *

Slide 122

Slide 122 text

Continue with the rest of the query CALL spatial.withinDistance('geom',
 {latitude: 37.563440, longitude: -122.322265}, 1) 
 YIELD node AS d WITH d, d.wkt AS wkt, d.state AS state, d.district AS district LIMIT 1 MATCH (d)<-[:REPRESENTS]-(l:Legislator) MATCH (l)-[:SERVES_ON]->(c:Committee) MATCH (c)<-[:REFERRED_TO]-(b:Bill) MATCH (b)-[:DEALS_WITH]->(s:Subject) RETURN *

Slide 123

Slide 123 text

lyonwj.com/2016/08/09/neo4j-spatial-procedures- congressional-boundaries/

Slide 124

Slide 124 text

Graph-based Machine Learning

Slide 125

Slide 125 text

No content

Slide 126

Slide 126 text

No content

Slide 127

Slide 127 text

Annotating text CREATE (n:News) SET n.text = "Scores of people were already lying dead or injured inside a crowded Orlando nightclub, and the police had spent hours trying to connect with the gunman and end the situation without further violence. But when Omar Mateen threatened to set off explosives, the police decided to act, and pushed their way through a wall to end the bloody standoff."

Slide 128

Slide 128 text

Annotating text MATCH (n:News) CALL ga.nlp.annotate({text: n.text, id: id(n)}) YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result) RETURN result

Slide 129

Slide 129 text

Execute procedure MATCH (n:News) CALL ga.nlp.annotate({text: n.text, id: id(n)}) YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result) RETURN result

Slide 130

Slide 130 text

Relate to text node MATCH (n:News) CALL ga.nlp.annotate({text: n.text, id: id(n)}) YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result) RETURN result

Slide 131

Slide 131 text

No content

Slide 132

Slide 132 text

Graph Algorithms

Slide 133

Slide 133 text

No content

Slide 134

Slide 134 text

Insights from Algorithms

Slide 135

Slide 135 text

Graph

Slide 136

Slide 136 text

Graph of Thrones

Slide 137

Slide 137 text

• Single Source Short Path • All Pairs SSP • Parallel BFS / DFS • Minimum Weight Spanning Tree • Shortest Path • A* • Yen’s K-shortest paths • Random Walk • Strongly-Connected Components • Union Find / WCC • Label Propagation • Louvain • Triangle-Count / Clustering Coefficent • PageRank (baseline) • Betweeness • Closeness • Degree • Harmonic (new!) https://neo4j.com/docs/graph-algorithms/current/

Slide 138

Slide 138 text

Usage 1.Call as Cypher procedure 2.Pass in specification (Label, Prop, Query) and configuration 3.Execute and return results A. ~.stream variant returns (a lot) of results CALL algo..stream('Label','TYPE', {conf}) YIELD nodeId, score B. non-stream variant writes results to graph and returns statistics
 CALL algo.('Label','TYPE', {conf})

Slide 139

Slide 139 text

Cypher Projection Pass in Cypher statement for node and relationship lists. 
 CALL algo.( 'MATCH ... RETURN id(n)', 'MATCH (n)-->(m) RETURN id(n) as source, id(m) as target', 
 {graph:'cypher'})

Slide 140

Slide 140 text

Graph Algorithms Sandbox neo4j.com/sandbox

Slide 141

Slide 141 text

Graph ML Models

Slide 142

Slide 142 text

No content

Slide 143

Slide 143 text

What’s In It? • Linear regression (Lauren Shin) • Multiple linear regression (Lauren Shin) • DeepGL/DeepWalk (Mark Needham) • …more coming soon!

Slide 144

Slide 144 text

https://towardsdatascience.com/graphs-and-linear-regression-734d1446e9cd

Slide 145

Slide 145 text

Graph Visualization

Slide 146

Slide 146 text

No content

Slide 147

Slide 147 text

No content

Slide 148

Slide 148 text

No content

Slide 149

Slide 149 text

var viz; function draw() { var config = { container_id: "viz", server_url: "bolt://localhost:7687", server_user: "neo4j", server_password: "sorts-swims-burglaries", labels: { "Character": { "caption": "name", "size": "pagerank", "community": "community" } }, relationships: { "INTERACTS": { "thickness": "weight", "caption": false } }, initial_cypher: "MATCH (n)-[r:INTERACTS]->(m) RETURN *" }; viz = new NeoVis.default(config); viz.render(); }

Slide 150

Slide 150 text

var viz; function draw() { var config = { container_id: "viz", server_url: "bolt://localhost:7687", server_user: "neo4j", server_password: "sorts-swims-burglaries", labels: { "Character": { "caption": "name", "size": "pagerank", "community": "community" } }, relationships: { "INTERACTS": { "thickness": "weight", "caption": false } }, initial_cypher: "MATCH (n)-[r:INTERACTS]->(m) RETURN *" }; viz = new NeoVis.default(config); viz.render(); }

Slide 151

Slide 151 text

var viz; function draw() { var config = { container_id: "viz", server_url: "bolt://localhost:7687", server_user: "neo4j", server_password: "sorts-swims-burglaries", labels: { "Character": { "caption": "name", "size": "pagerank", "community": "community" } }, relationships: { "INTERACTS": { "thickness": "weight", "caption": false } }, initial_cypher: "MATCH (n)-[r:INTERACTS]->(m) RETURN *" }; viz = new NeoVis.default(config); viz.render(); }

Slide 152

Slide 152 text

GraphQL

Slide 153

Slide 153 text

What is it? GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data.

Slide 154

Slide 154 text

What is it? GraphQL is a query language for your API, and a server- side runtime for executing queries by using a type system you define for your data.

Slide 155

Slide 155 text

What is it? GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data.

Slide 156

Slide 156 text

What is it? GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. type Planet {
 name: String
 climate: String
 } type Character {
 name: String
 friends: [Character]
 homeWorld: Planet
 species: Species
 } type Species {
 name: String
 lifespan: Int
 origin: Planet
 }

Slide 157

Slide 157 text

Manual mapping code

Slide 158

Slide 158 text

No content

Slide 159

Slide 159 text

Auto translating GraphQL → Cypher github.com/neo4j-graphql/neo4j-graphql github.com/neo4j-graphql/neo4j-graphql-js

Slide 160

Slide 160 text

Server-side Java extension

Slide 161

Slide 161 text

No content

Slide 162

Slide 162 text

conf/neo4j.conf dbms.unmanaged_extension_classes=org.neo4j.graphql=/graphql
 dbms.security.procedures.whitelist=graphql.*

Slide 163

Slide 163 text

CALL graphql.idl('
 type Movie { title: String! released: Int actors: [Person] @relation(name:"ACTED_IN",direction:IN) } type Person { name: String! born: Int movies: [Movie] @relation(name:"ACTED_IN") }' )

Slide 164

Slide 164 text

WITH '{ Person(born: 1961) { name, born } }' as query, {} as params CALL graphql.execute(query,params) 
 YIELD result UNWIND result.Person as p RETURN p.name, p.born

Slide 165

Slide 165 text

Javascript extension

Slide 166

Slide 166 text

No content

Slide 167

Slide 167 text

import {neo4jgraphql} from 'neo4j-graphql-js'; const resolvers = { Query: { Movie(object, params, ctx, resolveInfo) { return neo4jgraphql(object, params, ctx, resolveInfo); } } };

Slide 168

Slide 168 text

The GRAND stack

Slide 169

Slide 169 text

The GRAND stack GraphQL
 React
 Apollo
 Neo4j Database

Slide 170

Slide 170 text

dzone.com/refcardz/an-overview-of-graphql

Slide 171

Slide 171 text

How do I find out about more cool stuff???

Slide 172

Slide 172 text

This Week in Neo4j - Developer Update neo4j.com/tag/twin4j

Slide 173

Slide 173 text

Neo4j Community Site!

Slide 174

Slide 174 text

(you)-[:HAVE]->(questions)<-[:ANSWERS]-(jennifer) @JMHReif [email protected]

Slide 175

Slide 175 text

How many did we cover? • Bolt drivers: https://neo4j.com/developer/language-guides/ • User-defined procs/funcs: https://neo4j.com/developer/procedures-functions/ • APOC: https://github.com/neo4j-contrib/neo4j-apoc-procedures • Neo4j/Kafka: https://github.com/neo4j-contrib/neo4j-streams • Neo4j/RDF: https://github.com/jbarrasa/neosemantics • Neo4j/Elasticsearch: https://github.com/graphaware/neo4j-to-elasticsearch • Versioned graphs: https://github.com/h-omer/neo4j-versioner-core • Spatial: https://github.com/neo4j-contrib/spatial • NLP: https://github.com/graphaware/neo4j-nlp • Graph Algorithms: https://github.com/neo4j-contrib/neo4j-graph-algorithms • ML models: https://github.com/neo4j-graph-analytics/ml-models • Graph Visualization: https://github.com/neo4j-contrib/neovis.js • GraphQL/GRANDstack: https://github.com/neo4j-graphql