SlideShare ist ein Scribd-Unternehmen logo
1 von 163
Downloaden Sie, um offline zu lesen
Utilizing Powerful Extensions
for Analytics and Operations
~ 30 cool Neo4j extensions
in ~30 minutes
There will be code!
bit.ly/neo4j-30-things
Neo4j Developer Surface
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
Neo4j Developer Surface
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
Neo4j Bolt Drivers
Official Drivers
Community Drivers
Neo4j Developer Surface
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
Procedures
Functions
Aggregate Functions
Can be written in any JVM language
User Defined
Procedures
Callable Standalone
and in
Cypher Statements
CALL example.search('User','name:Brook*')
public class FullTextIndex {
@Context
public GraphDatabaseService db;
@Procedure( name = "example.search", mode = Procedure.Mode.READ )
public Stream<SearchHit> 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; }
}
}
public class FullTextIndex {
@Context
public GraphDatabaseService db;
@Procedure( name = "example.search", mode = Procedure.Mode.READ )
public Stream<SearchHit> 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; }
}
}
public class FullTextIndex {
@Context
public GraphDatabaseService db;
@Procedure( name = "example.search", mode = Procedure.Mode.READ )
public Stream<SearchHit> 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; }
}
}
try ( Driver driver = GraphDatabase.driver( "bolt://localhost",
Config.build().toConfig() ) ) {
try ( Session session = driver.session() ) {
String call = "CALL example.search('User',$query)";
Map<String,Object> params = singletonMap( "query", "name:Brook*");
StatementResult result = session.run( call, params);
while ( result.hasNext() {
// process results
}
}
}
try ( Driver driver = GraphDatabase.driver( "bolt://localhost",
Config.build().toConfig() ) ) {
try ( Session session = driver.session() ) {
String call = "CALL example.search('User',$query)";
Map<String,Object> params = singletonMap( "query", "name:Brook*");
StatementResult result = session.run( call, params);
while ( result.hasNext() {
// process results
}
}
}
User Defined
Functions
Useable in any Cypher
expression or lightweight
computation
RETURN example.join(['Hello', 'World'],' ')
=> "Hello World"
public class Join {
@UserFunction
@Description("example.join(['s1','s2',...], delimiter)
- join the given strings with the given delimiter.")
public String join(
@Name("strings") List<String> strings,
@Name(value = "delimiter", defaultValue = ",") String delimiter ) {
if ( strings == null || delimiter == null ) {
return null;
}
return String.join( delimiter, strings );
}
}
public class Join {
@UserFunction
@Description("example.join(['s1','s2',...], delimiter)
- join the given strings with the given delimiter.")
public String join(
@Name("strings") List<String> strings,
@Name(value = "delimiter", defaultValue = ",") String delimiter ) {
if ( strings == null || delimiter == null ) {
return null;
}
return String.join( delimiter, strings );
}
}
public class Join {
@UserFunction
@Description("example.join(['s1','s2',...], delimiter)
- join the given strings with the given delimiter.")
public String join(
@Name("strings") List<String> strings,
@Name(value = "delimiter", defaultValue = ",") String delimiter ) {
if ( strings == null || delimiter == null ) {
return null;
}
return String.join( delimiter, strings );
}
}
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();
}
}
User Defined
Aggregation Functions
Custom, efficient aggregations
for Data Science and BI
UNWIND ['abc', 'abcd', 'ab'] AS string
RETURN example.longestString(string)
=> 'abcd'
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; }
}
}
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; }
}
}
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; }
}
}
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; }
}
}
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();
}
}
Awesome Procedures
On Cypher
> 400
procedures and functions
Data Integration
Load from a relational database
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
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
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
Load XML
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)
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)
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)
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)
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)
MERGE (point:Point {id: id})
SET point.latitude = latitude,
point.longitude = longitude
MERGE (user:User {name: userName})
MERGE (user)-[:EDITED]->(point)
Load JSON
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)
)
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
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)
)
Graph Refactorings
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
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
apoc.create.addLabels
MATCH (n:Movie)
CALL apoc.create.addLabels( id(n), [ n.genre ] ) YIELD node
REMOVE node.genre
RETURN node
Cypher Execution
Run large scale updates
CALL apoc.periodic.iterate(
'MATCH (n:Person) RETURN n',
'SET n.name = n.firstName + " " + n.lastName',
{batchSize:10000, parallel:true})
Utility Functions
Compute soundex encoding of a string
CALL apoc.text.phonetic('Hello, dear User!')
YIELD value
RETURN value
// will return 'H436'
How similar do two strings sound?
CALL apoc.text.phoneticDelta(
'Hello Mr Rabbit', 'Hello Mr Ribbit')
// will return '4' (very similar)
Extract domain names
WITH 'http://www.example.com/all-the-things' AS url
RETURN apoc.data.domain(url)
// will return 'www.example.com'
Date to Timestamp
RETURN apoc.date.parse(
'2015/03/25 03:15:59',
's',
'yyyy/MM/dd HH:mm:ss'
)
// will return 1427253359
Timestamp to Date
RETURN apoc.date.format(
1427253359,
's',
'yyyy/MM/dd HH:mm:ss'
)
// will return "2015/03/25 03:15:59"
And many more!
RDF and Graphs
Import RDF triples
semantics.importRDF
CALL semantics.importRDF("file:///industry.ntriples","N-Triples", {})
Thomson Reuters' OpenPermID Graph
Graph Aided Search
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
conf/neo4j.conf
CALL ga.es.queryNode('{"query":
{"match":{"name":"alessandro"}}}')
YIELD node, score
RETURN node, score
Find nodes
CALL ga.es.queryRelationship('{"query":
{"match":{"city":"paris"}}}')
YIELD relationship, score
RETURN relationship, score
Find relationships
dzone.com/refcardz/graph-powered-search-neo4j-amp-elasticsearch
Versioned Graphs
CALL graph.versioner.init('Person',
{ssn: 123456789, name: 'Marco'},
{address: 'Via Roma 11'}
)
Create node
CALL graph.versioner.init('Person',
{ssn: 123456789, name: 'Marco'},
{address: 'Via Roma 11'}
)
Immutable properties
CALL graph.versioner.init('Person',
{ssn: 123456789, name: 'Marco'},
{address: 'Via Roma 11'}
)
State properties
MATCH (p:Person {name: "Marco"})
WITH p
CALL graph.versioner.update(p, {address: 'Via Roma 12'})
YIELD node
RETURN node
Update state
MATCH (p:Person {name: "Marco"})
WITH p
CALL graph.versioner.update(p, {address: 'Via Roma 12'})
YIELD node
RETURN node
Pass in the new state
Spatial
lyonwj.com/2016/08/09/neo4j-spatial-procedures-congressional-boundaries/
CALL spatial.addWKTLayer('geom', 'wkt')
Create spatial index
CREATE (d:District {...})
SET d.wkt = 'MULTIPOLYGON(((23.22, ... )))'
Add spatial property to nodes
MATCH (d:District)
WITH collect(d) AS districts
CALL spatial.addNodes('geom', districts) YIELD node
RETURN count(*)
Add nodes to spatial index
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 *
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 *
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 *
Continue with the rest of the query
lyonwj.com/2016/08/09/neo4j-spatial-procedures-congressional-boundaries/
Graph Based
Machine Learning
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."
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
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
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
Relate to text node
Graph Algorithms
Insights from Algorithms
Graph of Thrones
● Community Detection
● Centrality
Graph of Thrones - Centrality
Neo4j
Native Graph
Database
Analytics
Integrations
Cypher Query
Language
Wide Range of
APOC Procedures
Optimized
Graph Algorithms
Finds the optimal
path or evaluates
route availability and
quality
Evaluates how a
group is clustered
or partitioned
Determines the
importance of distinct
nodes in the network
Single Source Short Path
All-Nodes SSP
Parallel BFS / DFS
Strongly Connected
Components
Union Find / WCC
Label Propagation
Louvain
Triangle-Count /
Clustering Coefficent
PageRank (baseline)
Betweeness
Closeness
Degree
1.Call as Cypher procedure
2.Pass in specification (Label, Prop, Query) and configuration
3.~.stream variant returns (a lot) of results
CALL algo.<name>.stream('Label','TYPE', {conf})
YIELD nodeId, score
4.non-stream variant writes results to graph
and returns statistics
CALL algo.<name>('Label','TYPE', {conf})
Usage
Pass in Cypher statement for node and relationship lists.
CALL algo.<name>(
'MATCH ... RETURN id(n)',
'MATCH (n)-->(m)
RETURN id(n) as source, id(m) as target',
{graph:'cypher'})
Cypher Projection
DBpedia
CALL algo.pageRank.stream('Page', 'Link', {iterations:5})
YIELD node, score
WITH *
ORDER BY score DESC
LIMIT 5
RETURN node.title, score
Important pages
+--------------------------------------+
| node.title | score |
+--------------------------------------+
| "United States" | 13349.2 |
| "Animal" | 6077.77 |
| "France" | 5025.61 |
| "List of sovereign states" | 4913.92 |
| "Germany" | 4662.32 |
+--------------------------------------+
5 rows 20 seconds
CALL algo.labelPropagation()
Largest Clusters
CALL algo.labelPropagation()
MATCH (n:Page)
WITH n ORDER BY n.pagerank DESC
LIMIT 1000000
WITH n.partition AS partition,
count(*) AS clusterSize,
collect(n.title) AS pages
RETURN pages[0] AS mainPage,
pages[1..10] AS otherPages
ORDER BY clusterSize DESC
LIMIT 20
Largest Clusters
Graph Algorithms Sandbox
neo4j.com/sandbox
Graph Visualization
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();
}
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();
}
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();
}
GraphQL
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.
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.
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.
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.
What is it?
type Planet {
name: String
climate: String
}
type Character {
name: String
friends: [Character]
homeWorld: Planet
species: Species
}
type Species {
name: String
lifespan: Int
origin: Planet
}
Manual mapping code
Auto translating GraphQL → Cypher
github.com/neo4j-graphql/neo4j-graphql
github.com/neo4j-graphql/neo4j-graphql-js
Neo4j-GraphQL Database Extension
Neo4j serves GraphQL endpoint directly
dbms.unmanaged_extension_classes=org.neo4j.graphql=/graphql
dbms.security.procedures.whitelist=graphql.*
conf/neo4j.conf
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")
}'
)
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
JavaScript Library
import { neo4jgraphql } from 'neo4j-graphql-js';
const resolvers = {
Query: {
Movie(object, params, ctx, resolveInfo) {
return neo4jgraphql(object, params, ctx, resolveInfo);
}
}
};
The GRAND stack
grandstack.io
The GRAND stack
GraphQL
React
Apollo
Neo4j Database
dzone.com/refcardz/an-overview-of-graphql
How do I find out
about more cool stuff?
awesome-*
This Week in Neo4j - Developer Update
neo4j.com/tag/twin4j
We want to hear from YOU
bit.ly/neo4j-survey
Get Dressed: Neo4j Graph Gear Store
graphgearstore.com
Toronto Meetup - Tuesday May 8th
meetup.com/Women-Who-Code-Toront
o
(you)-[:HAVE]->(:Question)<-[:ANSWERS]-(will)

Weitere ähnliche Inhalte

Was ist angesagt?

Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
Sages
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 

Was ist angesagt? (19)

Python database interfaces
Python database  interfacesPython database  interfaces
Python database interfaces
 
"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014
 
Presto in Treasure Data
Presto in Treasure DataPresto in Treasure Data
Presto in Treasure Data
 
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash courseCodepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
Codepot - Pig i Hive: szybkie wprowadzenie / Pig and Hive crash course
 
XML-Motor
XML-MotorXML-Motor
XML-Motor
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with Slick
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines
 
GPars For Beginners
GPars For BeginnersGPars For Beginners
GPars For Beginners
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
 
JDK1.7 features
JDK1.7 featuresJDK1.7 features
JDK1.7 features
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
 
FunctionalJS - George Shevtsov
FunctionalJS - George ShevtsovFunctionalJS - George Shevtsov
FunctionalJS - George Shevtsov
 
ROracle
ROracle ROracle
ROracle
 
Shrug2017 arcpy data_and_you
Shrug2017 arcpy data_and_youShrug2017 arcpy data_and_you
Shrug2017 arcpy data_and_you
 
The Ring programming language version 1.5.1 book - Part 32 of 180
The Ring programming language version 1.5.1 book - Part 32 of 180The Ring programming language version 1.5.1 book - Part 32 of 180
The Ring programming language version 1.5.1 book - Part 32 of 180
 
Accelerating Local Search with PostgreSQL (KNN-Search)
Accelerating Local Search with PostgreSQL (KNN-Search)Accelerating Local Search with PostgreSQL (KNN-Search)
Accelerating Local Search with PostgreSQL (KNN-Search)
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 

Ähnlich wie Utilizing Powerful Extensions for Analytics and Operations

Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
偉格 高
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
Sven Haiges
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
Ben Lin
 

Ähnlich wie Utilizing Powerful Extensions for Analytics and Operations (20)

GraphTour - Utilizing Powerful Extensions for Analytics & Operations
GraphTour - Utilizing Powerful Extensions for Analytics & OperationsGraphTour - Utilizing Powerful Extensions for Analytics & Operations
GraphTour - Utilizing Powerful Extensions for Analytics & Operations
 
3 database-jdbc(1)
3 database-jdbc(1)3 database-jdbc(1)
3 database-jdbc(1)
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
MongoDB + Java - Everything you need to know
MongoDB + Java - Everything you need to know MongoDB + Java - Everything you need to know
MongoDB + Java - Everything you need to know
 
Mongo+java (1)
Mongo+java (1)Mongo+java (1)
Mongo+java (1)
 
Go react codelab
Go react codelabGo react codelab
Go react codelab
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
Spring boot
Spring boot Spring boot
Spring boot
 
NoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love StoryNoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love Story
 
CouchDB on Android
CouchDB on AndroidCouchDB on Android
CouchDB on Android
 
Flask and Angular: An approach to build robust platforms
Flask and Angular:  An approach to build robust platformsFlask and Angular:  An approach to build robust platforms
Flask and Angular: An approach to build robust platforms
 
JDBC Tutorial
JDBC TutorialJDBC Tutorial
JDBC Tutorial
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
Next-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and PrismaNext-generation API Development with GraphQL and Prisma
Next-generation API Development with GraphQL and Prisma
 
GraphQL & Prisma from Scratch
GraphQL & Prisma from ScratchGraphQL & Prisma from Scratch
GraphQL & Prisma from Scratch
 
CouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourCouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 Hour
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Javascript Everywhere From Nose To Tail
Javascript Everywhere From Nose To TailJavascript Everywhere From Nose To Tail
Javascript Everywhere From Nose To Tail
 
Play 2.0
Play 2.0Play 2.0
Play 2.0
 

Mehr von Neo4j

Mehr von Neo4j (20)

Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansQIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdfNeo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
 
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdfRabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
 
Webinar - IA generativa e grafi Neo4j: RAG time!
Webinar - IA generativa e grafi Neo4j: RAG time!Webinar - IA generativa e grafi Neo4j: RAG time!
Webinar - IA generativa e grafi Neo4j: RAG time!
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG time
 
Neo4j: Data Engineering for RAG (retrieval augmented generation)
Neo4j: Data Engineering for RAG (retrieval augmented generation)Neo4j: Data Engineering for RAG (retrieval augmented generation)
Neo4j: Data Engineering for RAG (retrieval augmented generation)
 
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdfNeo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
 
Enabling GenAI Breakthroughs with Knowledge Graphs
Enabling GenAI Breakthroughs with Knowledge GraphsEnabling GenAI Breakthroughs with Knowledge Graphs
Enabling GenAI Breakthroughs with Knowledge Graphs
 
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdfNeo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
 
Neo4j Jesus Barrasa The Art of the Possible with Graph
Neo4j Jesus Barrasa The Art of the Possible with GraphNeo4j Jesus Barrasa The Art of the Possible with Graph
Neo4j Jesus Barrasa The Art of the Possible with Graph
 

Kürzlich hochgeladen

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 

Kürzlich hochgeladen (20)

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 

Utilizing Powerful Extensions for Analytics and Operations

  • 1. Utilizing Powerful Extensions for Analytics and Operations
  • 2. ~ 30 cool Neo4j extensions in ~30 minutes
  • 3.
  • 6. Neo4j Developer Surface 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
  • 7. Neo4j Developer Surface 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
  • 11. Neo4j Developer Surface 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
  • 13. Can be written in any JVM language
  • 17. public class FullTextIndex { @Context public GraphDatabaseService db; @Procedure( name = "example.search", mode = Procedure.Mode.READ ) public Stream<SearchHit> 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; } } }
  • 18. public class FullTextIndex { @Context public GraphDatabaseService db; @Procedure( name = "example.search", mode = Procedure.Mode.READ ) public Stream<SearchHit> 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; } } }
  • 19. public class FullTextIndex { @Context public GraphDatabaseService db; @Procedure( name = "example.search", mode = Procedure.Mode.READ ) public Stream<SearchHit> 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; } } }
  • 20. try ( Driver driver = GraphDatabase.driver( "bolt://localhost", Config.build().toConfig() ) ) { try ( Session session = driver.session() ) { String call = "CALL example.search('User',$query)"; Map<String,Object> params = singletonMap( "query", "name:Brook*"); StatementResult result = session.run( call, params); while ( result.hasNext() { // process results } } }
  • 21. try ( Driver driver = GraphDatabase.driver( "bolt://localhost", Config.build().toConfig() ) ) { try ( Session session = driver.session() ) { String call = "CALL example.search('User',$query)"; Map<String,Object> params = singletonMap( "query", "name:Brook*"); StatementResult result = session.run( call, params); while ( result.hasNext() { // process results } } }
  • 23. Useable in any Cypher expression or lightweight computation
  • 25. public class Join { @UserFunction @Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.") public String join( @Name("strings") List<String> strings, @Name(value = "delimiter", defaultValue = ",") String delimiter ) { if ( strings == null || delimiter == null ) { return null; } return String.join( delimiter, strings ); } }
  • 26. public class Join { @UserFunction @Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.") public String join( @Name("strings") List<String> strings, @Name(value = "delimiter", defaultValue = ",") String delimiter ) { if ( strings == null || delimiter == null ) { return null; } return String.join( delimiter, strings ); } }
  • 27. public class Join { @UserFunction @Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.") public String join( @Name("strings") List<String> strings, @Name(value = "delimiter", defaultValue = ",") String delimiter ) { if ( strings == null || delimiter == null ) { return null; } return String.join( delimiter, strings ); } }
  • 28. 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(); } }
  • 30. Custom, efficient aggregations for Data Science and BI
  • 31. UNWIND ['abc', 'abcd', 'ab'] AS string RETURN example.longestString(string) => 'abcd'
  • 32. 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; } } }
  • 33. 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; } } }
  • 34. 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; } } }
  • 35. 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; } } }
  • 36. 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(); } }
  • 37.
  • 38.
  • 40.
  • 41.
  • 42. > 400 procedures and functions
  • 43.
  • 44.
  • 46. Load from a relational database
  • 47. 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
  • 48. 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
  • 49. 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
  • 51. 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)
  • 52. 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)
  • 53. 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)
  • 54. 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)
  • 55. 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) MERGE (point:Point {id: id}) SET point.latitude = latitude, point.longitude = longitude MERGE (user:User {name: userName}) MERGE (user)-[:EDITED]->(point)
  • 57. 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) )
  • 58. 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 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) )
  • 60. 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
  • 61. 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
  • 62. apoc.create.addLabels MATCH (n:Movie) CALL apoc.create.addLabels( id(n), [ n.genre ] ) YIELD node REMOVE node.genre RETURN node
  • 64. Run large scale updates CALL apoc.periodic.iterate( 'MATCH (n:Person) RETURN n', 'SET n.name = n.firstName + " " + n.lastName', {batchSize:10000, parallel:true})
  • 66. Compute soundex encoding of a string CALL apoc.text.phonetic('Hello, dear User!') YIELD value RETURN value // will return 'H436'
  • 67. How similar do two strings sound? CALL apoc.text.phoneticDelta( 'Hello Mr Rabbit', 'Hello Mr Ribbit') // will return '4' (very similar)
  • 68. Extract domain names WITH 'http://www.example.com/all-the-things' AS url RETURN apoc.data.domain(url) // will return 'www.example.com'
  • 69. Date to Timestamp RETURN apoc.date.parse( '2015/03/25 03:15:59', 's', 'yyyy/MM/dd HH:mm:ss' ) // will return 1427253359
  • 70. Timestamp to Date RETURN apoc.date.format( 1427253359, 's', 'yyyy/MM/dd HH:mm:ss' ) // will return "2015/03/25 03:15:59"
  • 73.
  • 74.
  • 79.
  • 80.
  • 81.
  • 82. 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 conf/neo4j.conf
  • 87.
  • 88.
  • 89. CALL graph.versioner.init('Person', {ssn: 123456789, name: 'Marco'}, {address: 'Via Roma 11'} ) Create node
  • 90. CALL graph.versioner.init('Person', {ssn: 123456789, name: 'Marco'}, {address: 'Via Roma 11'} ) Immutable properties
  • 91. CALL graph.versioner.init('Person', {ssn: 123456789, name: 'Marco'}, {address: 'Via Roma 11'} ) State properties
  • 92. MATCH (p:Person {name: "Marco"}) WITH p CALL graph.versioner.update(p, {address: 'Via Roma 12'}) YIELD node RETURN node Update state
  • 93. MATCH (p:Person {name: "Marco"}) WITH p CALL graph.versioner.update(p, {address: 'Via Roma 12'}) YIELD node RETURN node Pass in the new state
  • 95.
  • 98. CREATE (d:District {...}) SET d.wkt = 'MULTIPOLYGON(((23.22, ... )))' Add spatial property to nodes
  • 99. MATCH (d:District) WITH collect(d) AS districts CALL spatial.addNodes('geom', districts) YIELD node RETURN count(*) Add nodes to spatial index
  • 100. 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 * Query nodes by location
  • 101. 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 * Finds nodes within 1km
  • 102. 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 * Continue with the rest of the query
  • 105.
  • 106.
  • 107. 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." Annotating text
  • 108. MATCH (n:News) CALL ga.nlp.annotate({text: n.text, id: id(n)}) YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result) RETURN result Annotating text
  • 109. MATCH (n:News) CALL ga.nlp.annotate({text: n.text, id: id(n)}) YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result) RETURN result Execute procedure
  • 110. MATCH (n:News) CALL ga.nlp.annotate({text: n.text, id: id(n)}) YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result) RETURN result Relate to text node
  • 111.
  • 114. Graph of Thrones ● Community Detection ● Centrality
  • 115. Graph of Thrones - Centrality
  • 116. Neo4j Native Graph Database Analytics Integrations Cypher Query Language Wide Range of APOC Procedures Optimized Graph Algorithms
  • 117. Finds the optimal path or evaluates route availability and quality Evaluates how a group is clustered or partitioned Determines the importance of distinct nodes in the network
  • 118. Single Source Short Path All-Nodes SSP Parallel BFS / DFS Strongly Connected Components Union Find / WCC Label Propagation Louvain Triangle-Count / Clustering Coefficent PageRank (baseline) Betweeness Closeness Degree
  • 119. 1.Call as Cypher procedure 2.Pass in specification (Label, Prop, Query) and configuration 3.~.stream variant returns (a lot) of results CALL algo.<name>.stream('Label','TYPE', {conf}) YIELD nodeId, score 4.non-stream variant writes results to graph and returns statistics CALL algo.<name>('Label','TYPE', {conf}) Usage
  • 120. Pass in Cypher statement for node and relationship lists. CALL algo.<name>( 'MATCH ... RETURN id(n)', 'MATCH (n)-->(m) RETURN id(n) as source, id(m) as target', {graph:'cypher'}) Cypher Projection
  • 121.
  • 122.
  • 124. CALL algo.pageRank.stream('Page', 'Link', {iterations:5}) YIELD node, score WITH * ORDER BY score DESC LIMIT 5 RETURN node.title, score Important pages +--------------------------------------+ | node.title | score | +--------------------------------------+ | "United States" | 13349.2 | | "Animal" | 6077.77 | | "France" | 5025.61 | | "List of sovereign states" | 4913.92 | | "Germany" | 4662.32 | +--------------------------------------+ 5 rows 20 seconds
  • 126. CALL algo.labelPropagation() MATCH (n:Page) WITH n ORDER BY n.pagerank DESC LIMIT 1000000 WITH n.partition AS partition, count(*) AS clusterSize, collect(n.title) AS pages RETURN pages[0] AS mainPage, pages[1..10] AS otherPages ORDER BY clusterSize DESC LIMIT 20 Largest Clusters
  • 129.
  • 130.
  • 131.
  • 132. 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(); }
  • 133. 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(); }
  • 134. 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(); }
  • 135.
  • 137. 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. What is it?
  • 138. 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. What is it?
  • 139. 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. What is it?
  • 140.
  • 141. 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. What is it? type Planet { name: String climate: String } type Character { name: String friends: [Character] homeWorld: Planet species: Species } type Species { name: String lifespan: Int origin: Planet }
  • 143.
  • 144. Auto translating GraphQL → Cypher github.com/neo4j-graphql/neo4j-graphql github.com/neo4j-graphql/neo4j-graphql-js
  • 145. Neo4j-GraphQL Database Extension Neo4j serves GraphQL endpoint directly
  • 146.
  • 148. 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") }' )
  • 149. 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
  • 151.
  • 152. import { neo4jgraphql } from 'neo4j-graphql-js'; const resolvers = { Query: { Movie(object, params, ctx, resolveInfo) { return neo4jgraphql(object, params, ctx, resolveInfo); } } };
  • 156. How do I find out about more cool stuff?
  • 157.
  • 159. This Week in Neo4j - Developer Update neo4j.com/tag/twin4j
  • 160. We want to hear from YOU bit.ly/neo4j-survey
  • 161. Get Dressed: Neo4j Graph Gear Store graphgearstore.com
  • 162. Toronto Meetup - Tuesday May 8th meetup.com/Women-Who-Code-Toront o