SlideShare a Scribd company logo
1 of 131
APOC Pearls
Michael Hunger
Developer Relations Engineering, Neo4j
Follow @mesirii
APOC Unicorns
All Images by TeeTurtle.com
& Unstable Unicorns
Power Up
Extending Neo4j
Neo4j Execution Engine
User Defined
Procedure
Applications
Bolt
User Defined Procedures let you write
custom code that is:
• Written in any JVM language
• Deployed to the Database
• Accessed by applications via Cypher
APOC History
• My Unicorn Moment
• 3.0 was about to have
User Defined Procedures
• Add the missing utilities
• Grew quickly 50 - 150 - 450
• Active OSS project
• Many contributors
• Neo4j Sandbox
• Neo4j Desktop
• Neo4j Cloud
Available On
Install
• Utilities & Converters
• Data Integration
• Import / Export
• Graph Generation / Refactoring
• Transactions / Jobs / TTL
What's in the Box?
• Videos
• Documentation
• Browser Guide
• APOC Training
• Neo4j Community Forum
• apoc.help()
Where can I learn more?
If you learn one thing:
apoc.help("keyword)")
APOC
Video Series
Youtube Playlist
APOC Docs
• installation instructions
• videos
• searchable overview table
• detailed explaination
• examples
neo4j-contrib.github.io/neo4j-apoc-procedures
Browser Guide
:play apoc
• live examples
The Pearls -
That give you
Superpowers
17
Data
Integration
18
• Relational / Cassandra
• MongoDB, Couchbase,
ElasticSearch
• JSON, XML, CSV, XLS
• Cypher, GraphML
• ...
Data Integration
apoc.load.json
• load json from web-apis and files
• JSON Path
• streaming JSON
• compressed data
https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_load_json
WITH "https://api.stackexchange.com/2.2/questions?pagesize=100..." 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))
…
Huge
Transactions
23
Run large scale updates
CALL apoc.periodic.iterate(
'MATCH (n:Person) RETURN n',
'SET n.name = n.firstName + " " + n.lastName',
{batchSize:10000, parallel:true})
Run large scale updates
CALL apoc.periodic.iterate(
'LOAD CSV … AS row',
'MERGE (n:Node {id:row.id})
SET n.name = row.name',
{batchSize:10000, concurrency:10})
Utilities
26
Text Functions - apoc.text.*
indexOf, indexesOf
split, replace, regexpGroups
format
capitalize, decapitalize
random, lpad, rpad
snakeCase, camelCase, upperCase
charAt, hexCode
base64, md5, sha1,
https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_text_functions
Collection Functions - apoc.coll.*
sum, avg, min,max,stdev,
zip, partition, pairs
sort, toSet, contains, split
indexOf, .different
occurrences, frequencies, flatten
disjunct, subtract, union, …
set, insert, remove
https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3.4/docs/overview.adoc#collection-functions
Map Functions - apoc.map.*
• .fromNodes, .fromPairs,
.fromLists, .fromValues
• .merge
• .setKey,removeKey
• .clean(map,[keys],[values])
• .groupBy
https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3.4/docs/overview.adoc#map-functions
JSON - apoc.convert.*
.toJson([1,2,3])
.fromJsonList('[1,2,3]')
.fromJsonMap( '{"a":42,"b":"foo","c":[1,2,3]}')
.toTree([paths],[lowerCaseRels=true])
.getJsonProperty(node,key)
.setJsonProperty(node,key,complexValue)
Graph
Refactoring
31
• .cloneNodes
• .mergeNodes
• .extractNode
• .collapseNode
• .categorize
Relationship Modifications
• .to(rel, endNode)
• .from(rel, startNode)
• .invert(rel)
• .setType(rel, 'NEW-TYPE')
Aggregation Function - apoc.refactor.*
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
Triggers
35
Triggers
CALL apoc.trigger.add(
name, statement,{phase:before/after})
• pause/resume/list/remove
• Transaction-Event-Handler calls cypher statement
• parameters: createdNodes, assignedNodeProperties, deletedNodes,...
• utility functions to extract entities/properties from update-records
• stores in graph properties
Time to Live
37
enable in config: apoc.ttl.enabled=true
Label :TTL
apoc.date.expire(In)(node, time, unit)
Creates Index on :TTL(ttl)
Time To Live TTL
background job (every 60s - configurable)
that runs:
MATCH (n:TTL)
WHERE n.ttl > timestamp()
WITH n LIMIT 1000
DET DELETE n
Time To Live TTL
Aggregation
Functions
40
Aggregation Function - apoc.agg.*
• more efficient variants of collect(x)[a..b]
• .nth,.first,.last,.slice
• .median(x)
• .percentiles(x,[0.5,0.9])
• .product(x)
• .statistics() provides a full
numeric statistic
Graph
Grouping
42
Graph Grouping
MATCH (p:Person) set p.decade = b.born / 10;
MATCH (p1:Person)-->()<--(p2:Person)
WITH p1,p2,count(*) as c
MERGE (p1)-[r:INTERACTED]-(p2)
ON CREATE SET r.count = c
CALL apoc.nodes.group(['Person'],['decade'])
YIELD node, relationship RETURN *;
Cypher
Procedures
44
apoc.custom.asProcedure/asFunction
(name,statement, columns, params)
• Register statements as real procedures & functions
• 'custom' namespace prefix
• Pass parameters, configure result columns
• Stored in graph and distributed across cluster
Custom Procedures (WIP)
call apoc.custom.asProcedure('neighbours',
'MATCH (n:Person {name:$name})-->(nb)
RETURN neighbour',
[['neighbour','NODE']],[['name','STRING']]);
call custom.neighbours('Joe') YIELD neighbour;
Custom Procedures (WIP)
Report Issues
Contribute!
Ask Questions
neo4j.com/slack community.neo4j.com
APOC on GitHub
Join the
Workshop
tomorrow!
Any Questions?
Best
Question
gets a box!
Expand Operation
53
Expand Operations
Customized path expansion from start node(s)
• Min/max traversals
• Limit number of results
• Optional (no rows removed if no results)
• Choice of BFS/DFS expansion
• Custom uniqueness (restrictions on visitations of nodes/rels)
• Relationship and label filtering
• Supports repeating sequences
Expand Operations
apoc.path.expand(startNode(s), relationshipFilter, labelFilter, minLevel, maxLevel) YIELD path
• The original, when you don’t need much customization
apoc.path.expandConfig(startNode(s), configMap) YIELD path
• Most flexible, rich configuration map
apoc.path.subgraphNodes(startNode(s), configMap) YIELD node
• Only distinct nodes, don't care about paths
apoc.path.spanningTree(startNode(s), configMap) YIELD path
• Only one distinct path to each node
apoc.path.subgraphAll(startNode(s), configMap) YIELD nodes, relationships
• Only (collected) distinct nodes (and all rels between them)
Config map values
• minLevel: int
• maxLevel: int
• relationshipFilter
• labelFilter
• uniqueness: (‘RELATIONSHIP_PATH’, ’NODE_GLOBAL’, ‘NODE_PATH’, etc)
• bfs: boolean,
• filterStartNode: boolean
• limit: int
• optional: boolean
• endNodes: [nodes]
• terminatorNodes: [nodes]
• sequence
• beginSequenceAtStart: boolean
Relationship Filter
• '<ACTED_IN' - Incoming Rel
• 'DIRECTED>' - Outgoing Rel
• 'REVIEWED' - Any direction
• '<ACTED_IN | DIRECTED> | REVIEWED' - Multiple, in varied directions
• You can't do that with Cypher
-[ACTED_IN|DIRECTED|REVIEWED]->
Label Filter
What is/isn't allowed during expansion, and what is/isn't returned
• '-Director' – Blacklist, not allowed in path
• '+Person' –Whitelist, only allowed in path (no whitelist = all allowed)
• '>Reviewer' – End node, only return these, and continue expansion
• '/Actor:Producer' – Terminator node, only return these, stop expansion
'Person|Movie|-Director|>Reviewer|/Actor:Producer' – Combine them
Sequences
Repeating sequences of relationships, labels, or both.
Uses labelFilter and relationshipFilter, just add commas
Or use sequence for both together
labelFilter:'Post | -Blocked, Reply, >Admin'
relationshipFilter:'NEXT>,<FROM,POSTED>|REPLIED>'
sequence:'Post |-Blocked, NEXT>, Reply, <FROM, >Admin,
POSTED>| REPLIED>'
End nodes / Terminator nodes
What if we already have the nodes that should end the expansion?
endNodes – like filter, but takes a collection of nodes (or ids)
terminatorNodes – like filter (stop expand), but also takes a collection
(whitelistNodes and blacklistNodes too! )
Can be used with labelFilter or sequence, but continue or include must be unanimous
End nodes / Terminator nodes
What if we already have the nodes that should end the expansion?
endNodes – like filter, but takes a collection of nodes (or ids)
terminatorNodes – like filter (stop expand), but also takes a collection
(whitelistNodes and blacklistNodes too! )
Can be used with labelFilter or sequence, but continue or include must be unanimous
Bolt Connector
62
Bolt Connector
CALL apoc.bolt.execute(url, statement, params, config) YIELD row
CALL apoc.bolt.load(url, statement, params, config) YIELD row
call apoc.bolt.load("bolt://user:password@localhost:7687","
match(p:Person {name:{name}}) return p", {name:'Michael'})
supports bolt connector parameters
returns: scalars, Maps (row), virtual nodes,rels,paths
Connect to Community
Graph
"bolt://all:readonly@138.197.15.1"
and load all Meetup Group
64
Conversion Functions
65
Turn "[1,2,3]" into a Cypher
List
in plain Cypher
66
Turn JSON List into Cypher List
with "[1,2,3]" as str
with split(substring(str,1, length(str)-2),",") as numbers
return [x IN numbers| toInteger(x)]
apoc.convert.toJson
apoc.convert.fromJsonMap
apoc.convert.fromJsonList
JSON Conversion Functions
https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_from_tojson
Conversion Functions
apoc.convert.toString,.toBoolean,.toFloat,.toInteger
apoc.convert.toMap
apoc.convert.toList,.toSet
apoc.convert.toNode,.toRelationship
Logging
70
Logging
Triggers
72
Gephi Integration
73
Gephi Integration
match path = (:Person)-[:ACTED_IN]->(:Movie)
WITH path LIMIT 1000
with collect(path) as paths
call apoc.gephi.add(null,'workspace0', paths) yield nodes,
relationships, time
return nodes, relationships, time
incremental send to Gephi, needs Gephi Streaming extension
Graph Refactorings
75
Refactor the movie
graph
76
Cypher Execution
77
apoc.cypher.run(fragment, params)
apoc.cypher.doIt(fragment, params)
apoc.cypher.runTimeboxed
apoc.cypher.runFile(file or url,{config})
apoc.cypher.runSchemaFile(file or url,{config})
apoc.cypher.runMany('cypher;nstatements;',{params},{config})
apoc.cypher.mapParallel(fragment, params, list-to-parallelize)
Cypher Execution
Check out the other
periodic procs
Try apoc.periodic.iterate
example
79
Graph Grouping
80
Warmup
81
Warmup
• load page-cache
• page-skipping
• new implementation based on PageCache.*
• nodes + rels + rel-groups
• properties
• string / array properties
• index pages
Monitoring
83
Monitoring
• apoc.monitor.ids
• apoc.monitor.kernel
• apoc.monitor.store
• apoc.monitor.tx
• apoc.monitor.locks(minWaitTime long)
Conditional Cypher
Execution
85
Conditional Cypher Execution
CALL apoc.[do.]when(condition, ifQuery, elseQuery, params)
CALL apoc.[do.]case([condition, query, condition, query, …​],
elseQuery, params)
Graph Generation
87
Graph Generation
• apoc.generate.er(noNodes, noEdges, 'label', 'type')
Erdos-Renyi model (uniform)
• apoc.generate.ws(noNodes, degree, beta, 'label', 'type')
Watts-Strogatz model (clusters)
• apoc.generate.ba(noNodes, edgesPerNode, 'label', 'type')
Barabasi-Albert model (preferential attachment
• apoc.generate.complete(noNodes, 'label', 'type')
• apoc.generate.simple([degrees], 'label', 'type')
Locking
89
Locking
call apoc.lock.nodes([nodes])
call apoc.lock.rels([relationships])
call apoc.lock.all([nodes],[relationships])
JSON
91
Export
92
Export
apoc.export.csv .all / .data / .query
apoc.export.cypher
apoc.export.graphml
leaving off filename does stream cypher to client
Data Creation
94
Data Creation
CALL apoc.create.node(['Label'], {key:value,…​})
CALL apoc.create.nodes(['Label'], [{key:value,…​}])
CALL apoc.create.addLabels, .removeLabels
CALL apoc.create.setProperty
CALL apoc.create.setProperties
CALL apoc.create.relationship(from,'TYPE',{key:value,…​}, to)
CALL apoc.nodes.link([nodes],'REL_TYPE')
Virtual Entities
96
Virtual Entities
Function AND Procedure
apoc.create.vNode(['Label'], {key:value,…​}) YIELD node
apoc.create.vRelationship(from,TYPE,{key:value,…​}, to)
apoc.create.vPattern({_labels:[Label],key:value},'TYPE',
{key:value,…​}, {_labels:['LabelB'],key:value})
Try
apoc.date.* with datetime()
text, coll, map, convert funcs
98
And many more!
Latest Releases
Summer Release 3.4.0.2 (Aug 8)
Spring Release 3.4.0.1 (May 16)
Winter Release 3.3.0.2 (Feb 23)
TASK
Aggregation Functions
101
Latest Additions
• apoc.diff graph
• new text similarity functions
• CSV loader based on neo4j-
import format
• apoc.load.xls
• apoc.group.nodes
• Accessor functions for
(virtual) entities
• S3 Support
• HDFS Support
• apoc.index.addNodeMap
• apoc.path.create
• apoc.path.slice
• apoc.path.combine
• apoc.text.code(codepoint)
• stream apoc.export.cypher
• apoc.coll.combinations(),
apoc.coll.frequencies()
102
TASK
Which of these are you
interested in?
Ask / Try
103
Procedures / Functions from Cypher
CALL apoc.custom.asProcedure('answer','RETURN 42 as answer');
CALL custom.answer();
works also with parameters, and return columns declarations
CALL apoc.custom.asFunction('answer','RETURN $input','long',
[['input','number']]);
RETURN custom.answer(42) as answer;
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
Procedures
Functions
Aggregate Functions
Can be written in any JVM language
User Defined Procedures
108
Callable Standalone
and in
Cypher Statements
CALL example.search('User','name:Brook*')
How to build them
Developer Manual
Build a procedure or function
you'd like
start with
the template repo
github.com/neo4j-examples/neo4j-procedure-template
112
User Defined Procedures
User-defined procedures are
● @Procedure annotated, named Java Methods
○ default name: package + method
● take @Name'ed parameters (3.1. default values)
● return a Stream of value objects
● fields are turned into columns
● can use @Context injected GraphDatabaseService etc
● run within Transaction
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
}
}
}
Deploy & Register in Neo4j Server via neo4j-harness
Call & test via neo4j-java-driver
Deploying User Defined Procedures
Build or download (shadow) jar
● Drop jar-file into $NEO4J_HOME/plugins
● Restart server
● Procedure should be available
● Otherwise check neo4j.log / debug.log
User Defined
Functions
120
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
127
Custom, efficient aggregations
for Data Science and BI
Aggregation Function In APOC
• more efficient variants of collect(x)[a..b]
• apoc.agg.nth, apoc.agg.first, apoc.agg.last, apoc.agg.slice
• apoc.agg.median(x)
• apoc.agg.percentiles(x,[0.5,0.9])
• apoc.agg.product(x)
• apoc.agg.statistics() provides a full numeric statistic
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();
}
}
One Question / Comment
from each!

More Related Content

What's hot

Kubeflow Pipelines (with Tekton)
Kubeflow Pipelines (with Tekton)Kubeflow Pipelines (with Tekton)
Kubeflow Pipelines (with Tekton)Animesh Singh
 
NATS Streaming - an alternative to Apache Kafka?
NATS Streaming - an alternative to Apache Kafka?NATS Streaming - an alternative to Apache Kafka?
NATS Streaming - an alternative to Apache Kafka?Anton Zadorozhniy
 
Combine Spring Data Neo4j and Spring Boot to quickl
Combine Spring Data Neo4j and Spring Boot to quicklCombine Spring Data Neo4j and Spring Boot to quickl
Combine Spring Data Neo4j and Spring Boot to quicklNeo4j
 
Boost Your Neo4j with User-Defined Procedures
Boost Your Neo4j with User-Defined ProceduresBoost Your Neo4j with User-Defined Procedures
Boost Your Neo4j with User-Defined ProceduresNeo4j
 
Kubernetes introduction
Kubernetes introductionKubernetes introduction
Kubernetes introductionDongwon Kim
 
Designing High Availability for HashiCorp Vault in AWS
Designing High Availability for HashiCorp Vault in AWSDesigning High Availability for HashiCorp Vault in AWS
Designing High Availability for HashiCorp Vault in AWS☁ Bryan Krausen
 
End to end Machine Learning using Kubeflow - Build, Train, Deploy and Manage
End to end Machine Learning using Kubeflow - Build, Train, Deploy and ManageEnd to end Machine Learning using Kubeflow - Build, Train, Deploy and Manage
End to end Machine Learning using Kubeflow - Build, Train, Deploy and ManageAnimesh Singh
 
Container Runtime Security with Falco
Container Runtime Security with FalcoContainer Runtime Security with Falco
Container Runtime Security with FalcoMichael Ducy
 
Real-time Analytics with Trino and Apache Pinot
Real-time Analytics with Trino and Apache PinotReal-time Analytics with Trino and Apache Pinot
Real-time Analytics with Trino and Apache PinotXiang Fu
 
026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...
026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...
026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...Neo4j
 
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in ProductionKong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in ProductionFIWARE
 
Role based access control - RBAC - Kubernetes
Role based access control - RBAC - KubernetesRole based access control - RBAC - Kubernetes
Role based access control - RBAC - KubernetesMilan Das
 
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxConAnatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxConJérôme Petazzoni
 
Kubernetes Architecture - beyond a black box - Part 1
Kubernetes Architecture - beyond a black box - Part 1Kubernetes Architecture - beyond a black box - Part 1
Kubernetes Architecture - beyond a black box - Part 1Hao H. Zhang
 
FIWARE Training: API Umbrella
FIWARE Training: API UmbrellaFIWARE Training: API Umbrella
FIWARE Training: API UmbrellaFIWARE
 
Neo4J : Introduction to Graph Database
Neo4J : Introduction to Graph DatabaseNeo4J : Introduction to Graph Database
Neo4J : Introduction to Graph DatabaseMindfire Solutions
 
Neo4j GraphDay Seattle- Sept19- neo4j basic training
Neo4j GraphDay Seattle- Sept19- neo4j basic trainingNeo4j GraphDay Seattle- Sept19- neo4j basic training
Neo4j GraphDay Seattle- Sept19- neo4j basic trainingNeo4j
 

What's hot (20)

Kubeflow Pipelines (with Tekton)
Kubeflow Pipelines (with Tekton)Kubeflow Pipelines (with Tekton)
Kubeflow Pipelines (with Tekton)
 
NATS Streaming - an alternative to Apache Kafka?
NATS Streaming - an alternative to Apache Kafka?NATS Streaming - an alternative to Apache Kafka?
NATS Streaming - an alternative to Apache Kafka?
 
Combine Spring Data Neo4j and Spring Boot to quickl
Combine Spring Data Neo4j and Spring Boot to quicklCombine Spring Data Neo4j and Spring Boot to quickl
Combine Spring Data Neo4j and Spring Boot to quickl
 
Boost Your Neo4j with User-Defined Procedures
Boost Your Neo4j with User-Defined ProceduresBoost Your Neo4j with User-Defined Procedures
Boost Your Neo4j with User-Defined Procedures
 
Kubernetes introduction
Kubernetes introductionKubernetes introduction
Kubernetes introduction
 
Designing High Availability for HashiCorp Vault in AWS
Designing High Availability for HashiCorp Vault in AWSDesigning High Availability for HashiCorp Vault in AWS
Designing High Availability for HashiCorp Vault in AWS
 
End to end Machine Learning using Kubeflow - Build, Train, Deploy and Manage
End to end Machine Learning using Kubeflow - Build, Train, Deploy and ManageEnd to end Machine Learning using Kubeflow - Build, Train, Deploy and Manage
End to end Machine Learning using Kubeflow - Build, Train, Deploy and Manage
 
Container Runtime Security with Falco
Container Runtime Security with FalcoContainer Runtime Security with Falco
Container Runtime Security with Falco
 
Real-time Analytics with Trino and Apache Pinot
Real-time Analytics with Trino and Apache PinotReal-time Analytics with Trino and Apache Pinot
Real-time Analytics with Trino and Apache Pinot
 
026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...
026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...
026 Neo4j Data Loading (ETL_ELT) Best Practices - NODES2022 AMERICAS Advanced...
 
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in ProductionKong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
Kong, Keyrock, Keycloak, i4Trust - Options to Secure FIWARE in Production
 
ELK Stack
ELK StackELK Stack
ELK Stack
 
How to Use JSON in MySQL Wrong
How to Use JSON in MySQL WrongHow to Use JSON in MySQL Wrong
How to Use JSON in MySQL Wrong
 
Role based access control - RBAC - Kubernetes
Role based access control - RBAC - KubernetesRole based access control - RBAC - Kubernetes
Role based access control - RBAC - Kubernetes
 
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxConAnatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
Anatomy of a Container: Namespaces, cgroups & Some Filesystem Magic - LinuxCon
 
Kubernetes Architecture - beyond a black box - Part 1
Kubernetes Architecture - beyond a black box - Part 1Kubernetes Architecture - beyond a black box - Part 1
Kubernetes Architecture - beyond a black box - Part 1
 
FIWARE Training: API Umbrella
FIWARE Training: API UmbrellaFIWARE Training: API Umbrella
FIWARE Training: API Umbrella
 
Neo4J : Introduction to Graph Database
Neo4J : Introduction to Graph DatabaseNeo4J : Introduction to Graph Database
Neo4J : Introduction to Graph Database
 
Neo4j GraphDay Seattle- Sept19- neo4j basic training
Neo4j GraphDay Seattle- Sept19- neo4j basic trainingNeo4j GraphDay Seattle- Sept19- neo4j basic training
Neo4j GraphDay Seattle- Sept19- neo4j basic training
 
Apache Airflow
Apache AirflowApache Airflow
Apache Airflow
 

Similar to APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library

PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails BootcampMat Schaffer
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launchedMat Schaffer
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHiroshi SHIBATA
 
A Recovering Java Developer Learns to Go
A Recovering Java Developer Learns to GoA Recovering Java Developer Learns to Go
A Recovering Java Developer Learns to GoMatt Stine
 
Who pulls the strings?
Who pulls the strings?Who pulls the strings?
Who pulls the strings?Ronny
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...bobmcwhirter
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojureAbbas Raza
 
Ansible with oci
Ansible with ociAnsible with oci
Ansible with ociDonghuKIM2
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.jsChris Cowan
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Guillaume Laforge
 
Learning Puppet basic thing
Learning Puppet basic thing Learning Puppet basic thing
Learning Puppet basic thing DaeHyung Lee
 
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverageTesting NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoveragemlilley
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.jsorkaplan
 
Postgres Vienna DB Meetup 2014
Postgres Vienna DB Meetup 2014Postgres Vienna DB Meetup 2014
Postgres Vienna DB Meetup 2014Michael Renner
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffJAX London
 
#PDR15 - waf, wscript and Your Pebble App
#PDR15 - waf, wscript and Your Pebble App#PDR15 - waf, wscript and Your Pebble App
#PDR15 - waf, wscript and Your Pebble AppPebble Technology
 
Swift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-CSwift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-CAlexis Gallagher
 

Similar to APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library (20)

PTW Rails Bootcamp
PTW Rails BootcampPTW Rails Bootcamp
PTW Rails Bootcamp
 
wwc start-launched
wwc start-launchedwwc start-launched
wwc start-launched
 
Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
 
A Recovering Java Developer Learns to Go
A Recovering Java Developer Learns to GoA Recovering Java Developer Learns to Go
A Recovering Java Developer Learns to Go
 
Who pulls the strings?
Who pulls the strings?Who pulls the strings?
Who pulls the strings?
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Ansible with oci
Ansible with ociAnsible with oci
Ansible with oci
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Learning Puppet basic thing
Learning Puppet basic thing Learning Puppet basic thing
Learning Puppet basic thing
 
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverageTesting NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
 
Get to know PostgreSQL!
Get to know PostgreSQL!Get to know PostgreSQL!
Get to know PostgreSQL!
 
Logstash
LogstashLogstash
Logstash
 
Postgres Vienna DB Meetup 2014
Postgres Vienna DB Meetup 2014Postgres Vienna DB Meetup 2014
Postgres Vienna DB Meetup 2014
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard Wolff
 
#PDR15 - waf, wscript and Your Pebble App
#PDR15 - waf, wscript and Your Pebble App#PDR15 - waf, wscript and Your Pebble App
#PDR15 - waf, wscript and Your Pebble App
 
Swift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-CSwift, functional programming, and the future of Objective-C
Swift, functional programming, and the future of Objective-C
 

More from jexp

Looming Marvelous - Virtual Threads in Java Javaland.pdf
Looming Marvelous - Virtual Threads in Java Javaland.pdfLooming Marvelous - Virtual Threads in Java Javaland.pdf
Looming Marvelous - Virtual Threads in Java Javaland.pdfjexp
 
Easing the daily grind with the awesome JDK command line tools
Easing the daily grind with the awesome JDK command line toolsEasing the daily grind with the awesome JDK command line tools
Easing the daily grind with the awesome JDK command line toolsjexp
 
Looming Marvelous - Virtual Threads in Java
Looming Marvelous - Virtual Threads in JavaLooming Marvelous - Virtual Threads in Java
Looming Marvelous - Virtual Threads in Javajexp
 
GraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptx
GraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptxGraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptx
GraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptxjexp
 
Neo4j Connector Apache Spark FiNCENFiles
Neo4j Connector Apache Spark FiNCENFilesNeo4j Connector Apache Spark FiNCENFiles
Neo4j Connector Apache Spark FiNCENFilesjexp
 
How Graphs Help Investigative Journalists to Connect the Dots
How Graphs Help Investigative Journalists to Connect the DotsHow Graphs Help Investigative Journalists to Connect the Dots
How Graphs Help Investigative Journalists to Connect the Dotsjexp
 
The Home Office. Does it really work?
The Home Office. Does it really work?The Home Office. Does it really work?
The Home Office. Does it really work?jexp
 
Polyglot Applications with GraalVM
Polyglot Applications with GraalVMPolyglot Applications with GraalVM
Polyglot Applications with GraalVMjexp
 
Neo4j Graph Streaming Services with Apache Kafka
Neo4j Graph Streaming Services with Apache KafkaNeo4j Graph Streaming Services with Apache Kafka
Neo4j Graph Streaming Services with Apache Kafkajexp
 
How Graph Databases efficiently store, manage and query connected data at s...
How Graph Databases efficiently  store, manage and query  connected data at s...How Graph Databases efficiently  store, manage and query  connected data at s...
How Graph Databases efficiently store, manage and query connected data at s...jexp
 
Refactoring, 2nd Edition
Refactoring, 2nd EditionRefactoring, 2nd Edition
Refactoring, 2nd Editionjexp
 
New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...
New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...
New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...jexp
 
GraphQL - The new "Lingua Franca" for API-Development
GraphQL - The new "Lingua Franca" for API-DevelopmentGraphQL - The new "Lingua Franca" for API-Development
GraphQL - The new "Lingua Franca" for API-Developmentjexp
 
A whirlwind tour of graph databases
A whirlwind tour of graph databasesA whirlwind tour of graph databases
A whirlwind tour of graph databasesjexp
 
Practical Graph Algorithms with Neo4j
Practical Graph Algorithms with Neo4jPractical Graph Algorithms with Neo4j
Practical Graph Algorithms with Neo4jjexp
 
A Game of Data and GraphQL
A Game of Data and GraphQLA Game of Data and GraphQL
A Game of Data and GraphQLjexp
 
Querying Graphs with GraphQL
Querying Graphs with GraphQLQuerying Graphs with GraphQL
Querying Graphs with GraphQLjexp
 
Graphs & Neo4j - Past Present Future
Graphs & Neo4j - Past Present FutureGraphs & Neo4j - Past Present Future
Graphs & Neo4j - Past Present Futurejexp
 
Intro to Graphs and Neo4j
Intro to Graphs and Neo4jIntro to Graphs and Neo4j
Intro to Graphs and Neo4jjexp
 
Class graph neo4j and software metrics
Class graph neo4j and software metricsClass graph neo4j and software metrics
Class graph neo4j and software metricsjexp
 

More from jexp (20)

Looming Marvelous - Virtual Threads in Java Javaland.pdf
Looming Marvelous - Virtual Threads in Java Javaland.pdfLooming Marvelous - Virtual Threads in Java Javaland.pdf
Looming Marvelous - Virtual Threads in Java Javaland.pdf
 
Easing the daily grind with the awesome JDK command line tools
Easing the daily grind with the awesome JDK command line toolsEasing the daily grind with the awesome JDK command line tools
Easing the daily grind with the awesome JDK command line tools
 
Looming Marvelous - Virtual Threads in Java
Looming Marvelous - Virtual Threads in JavaLooming Marvelous - Virtual Threads in Java
Looming Marvelous - Virtual Threads in Java
 
GraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptx
GraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptxGraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptx
GraphConnect 2022 - Top 10 Cypher Tuning Tips & Tricks.pptx
 
Neo4j Connector Apache Spark FiNCENFiles
Neo4j Connector Apache Spark FiNCENFilesNeo4j Connector Apache Spark FiNCENFiles
Neo4j Connector Apache Spark FiNCENFiles
 
How Graphs Help Investigative Journalists to Connect the Dots
How Graphs Help Investigative Journalists to Connect the DotsHow Graphs Help Investigative Journalists to Connect the Dots
How Graphs Help Investigative Journalists to Connect the Dots
 
The Home Office. Does it really work?
The Home Office. Does it really work?The Home Office. Does it really work?
The Home Office. Does it really work?
 
Polyglot Applications with GraalVM
Polyglot Applications with GraalVMPolyglot Applications with GraalVM
Polyglot Applications with GraalVM
 
Neo4j Graph Streaming Services with Apache Kafka
Neo4j Graph Streaming Services with Apache KafkaNeo4j Graph Streaming Services with Apache Kafka
Neo4j Graph Streaming Services with Apache Kafka
 
How Graph Databases efficiently store, manage and query connected data at s...
How Graph Databases efficiently  store, manage and query  connected data at s...How Graph Databases efficiently  store, manage and query  connected data at s...
How Graph Databases efficiently store, manage and query connected data at s...
 
Refactoring, 2nd Edition
Refactoring, 2nd EditionRefactoring, 2nd Edition
Refactoring, 2nd Edition
 
New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...
New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...
New Features in Neo4j 3.4 / 3.3 - Graph Algorithms, Spatial, Date-Time & Visu...
 
GraphQL - The new "Lingua Franca" for API-Development
GraphQL - The new "Lingua Franca" for API-DevelopmentGraphQL - The new "Lingua Franca" for API-Development
GraphQL - The new "Lingua Franca" for API-Development
 
A whirlwind tour of graph databases
A whirlwind tour of graph databasesA whirlwind tour of graph databases
A whirlwind tour of graph databases
 
Practical Graph Algorithms with Neo4j
Practical Graph Algorithms with Neo4jPractical Graph Algorithms with Neo4j
Practical Graph Algorithms with Neo4j
 
A Game of Data and GraphQL
A Game of Data and GraphQLA Game of Data and GraphQL
A Game of Data and GraphQL
 
Querying Graphs with GraphQL
Querying Graphs with GraphQLQuerying Graphs with GraphQL
Querying Graphs with GraphQL
 
Graphs & Neo4j - Past Present Future
Graphs & Neo4j - Past Present FutureGraphs & Neo4j - Past Present Future
Graphs & Neo4j - Past Present Future
 
Intro to Graphs and Neo4j
Intro to Graphs and Neo4jIntro to Graphs and Neo4j
Intro to Graphs and Neo4j
 
Class graph neo4j and software metrics
Class graph neo4j and software metricsClass graph neo4j and software metrics
Class graph neo4j and software metrics
 

Recently uploaded

RadioAdProWritingCinderellabyButleri.pdf
RadioAdProWritingCinderellabyButleri.pdfRadioAdProWritingCinderellabyButleri.pdf
RadioAdProWritingCinderellabyButleri.pdfgstagge
 
办理学位证纽约大学毕业证(NYU毕业证书)原版一比一
办理学位证纽约大学毕业证(NYU毕业证书)原版一比一办理学位证纽约大学毕业证(NYU毕业证书)原版一比一
办理学位证纽约大学毕业证(NYU毕业证书)原版一比一fhwihughh
 
Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024
Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024
Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024thyngster
 
Heart Disease Classification Report: A Data Analysis Project
Heart Disease Classification Report: A Data Analysis ProjectHeart Disease Classification Report: A Data Analysis Project
Heart Disease Classification Report: A Data Analysis ProjectBoston Institute of Analytics
 
Semantic Shed - Squashing and Squeezing.pptx
Semantic Shed - Squashing and Squeezing.pptxSemantic Shed - Squashing and Squeezing.pptx
Semantic Shed - Squashing and Squeezing.pptxMike Bennett
 
Defining Constituents, Data Vizzes and Telling a Data Story
Defining Constituents, Data Vizzes and Telling a Data StoryDefining Constituents, Data Vizzes and Telling a Data Story
Defining Constituents, Data Vizzes and Telling a Data StoryJeremy Anderson
 
PKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptxPKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptxPramod Kumar Srivastava
 
RS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝Delhi
RS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝DelhiRS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝Delhi
RS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝Delhijennyeacort
 
Student profile product demonstration on grades, ability, well-being and mind...
Student profile product demonstration on grades, ability, well-being and mind...Student profile product demonstration on grades, ability, well-being and mind...
Student profile product demonstration on grades, ability, well-being and mind...Seán Kennedy
 
原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档
原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档
原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档208367051
 
科罗拉多大学波尔得分校毕业证学位证成绩单-可办理
科罗拉多大学波尔得分校毕业证学位证成绩单-可办理科罗拉多大学波尔得分校毕业证学位证成绩单-可办理
科罗拉多大学波尔得分校毕业证学位证成绩单-可办理e4aez8ss
 
Machine learning classification ppt.ppt
Machine learning classification  ppt.pptMachine learning classification  ppt.ppt
Machine learning classification ppt.pptamreenkhanum0307
 
NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...
NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...
NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...Amil Baba Dawood bangali
 
Advanced Machine Learning for Business Professionals
Advanced Machine Learning for Business ProfessionalsAdvanced Machine Learning for Business Professionals
Advanced Machine Learning for Business ProfessionalsVICTOR MAESTRE RAMIREZ
 
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...Jack DiGiovanna
 
Predicting Salary Using Data Science: A Comprehensive Analysis.pdf
Predicting Salary Using Data Science: A Comprehensive Analysis.pdfPredicting Salary Using Data Science: A Comprehensive Analysis.pdf
Predicting Salary Using Data Science: A Comprehensive Analysis.pdfBoston Institute of Analytics
 
Call Girls In Dwarka 9654467111 Escorts Service
Call Girls In Dwarka 9654467111 Escorts ServiceCall Girls In Dwarka 9654467111 Escorts Service
Call Girls In Dwarka 9654467111 Escorts ServiceSapana Sha
 
While-For-loop in python used in college
While-For-loop in python used in collegeWhile-For-loop in python used in college
While-For-loop in python used in collegessuser7a7cd61
 
Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)
Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)
Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)jennyeacort
 

Recently uploaded (20)

RadioAdProWritingCinderellabyButleri.pdf
RadioAdProWritingCinderellabyButleri.pdfRadioAdProWritingCinderellabyButleri.pdf
RadioAdProWritingCinderellabyButleri.pdf
 
办理学位证纽约大学毕业证(NYU毕业证书)原版一比一
办理学位证纽约大学毕业证(NYU毕业证书)原版一比一办理学位证纽约大学毕业证(NYU毕业证书)原版一比一
办理学位证纽约大学毕业证(NYU毕业证书)原版一比一
 
Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024
Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024
Consent & Privacy Signals on Google *Pixels* - MeasureCamp Amsterdam 2024
 
Heart Disease Classification Report: A Data Analysis Project
Heart Disease Classification Report: A Data Analysis ProjectHeart Disease Classification Report: A Data Analysis Project
Heart Disease Classification Report: A Data Analysis Project
 
Semantic Shed - Squashing and Squeezing.pptx
Semantic Shed - Squashing and Squeezing.pptxSemantic Shed - Squashing and Squeezing.pptx
Semantic Shed - Squashing and Squeezing.pptx
 
Defining Constituents, Data Vizzes and Telling a Data Story
Defining Constituents, Data Vizzes and Telling a Data StoryDefining Constituents, Data Vizzes and Telling a Data Story
Defining Constituents, Data Vizzes and Telling a Data Story
 
PKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptxPKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptx
 
RS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝Delhi
RS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝DelhiRS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝Delhi
RS 9000 Call In girls Dwarka Mor (DELHI)⇛9711147426🔝Delhi
 
Student profile product demonstration on grades, ability, well-being and mind...
Student profile product demonstration on grades, ability, well-being and mind...Student profile product demonstration on grades, ability, well-being and mind...
Student profile product demonstration on grades, ability, well-being and mind...
 
原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档
原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档
原版1:1定制南十字星大学毕业证(SCU毕业证)#文凭成绩单#真实留信学历认证永久存档
 
科罗拉多大学波尔得分校毕业证学位证成绩单-可办理
科罗拉多大学波尔得分校毕业证学位证成绩单-可办理科罗拉多大学波尔得分校毕业证学位证成绩单-可办理
科罗拉多大学波尔得分校毕业证学位证成绩单-可办理
 
Machine learning classification ppt.ppt
Machine learning classification  ppt.pptMachine learning classification  ppt.ppt
Machine learning classification ppt.ppt
 
NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...
NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...
NO1 Certified Black Magic Specialist Expert Amil baba in Lahore Islamabad Raw...
 
Advanced Machine Learning for Business Professionals
Advanced Machine Learning for Business ProfessionalsAdvanced Machine Learning for Business Professionals
Advanced Machine Learning for Business Professionals
 
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
 
Predicting Salary Using Data Science: A Comprehensive Analysis.pdf
Predicting Salary Using Data Science: A Comprehensive Analysis.pdfPredicting Salary Using Data Science: A Comprehensive Analysis.pdf
Predicting Salary Using Data Science: A Comprehensive Analysis.pdf
 
Call Girls In Dwarka 9654467111 Escorts Service
Call Girls In Dwarka 9654467111 Escorts ServiceCall Girls In Dwarka 9654467111 Escorts Service
Call Girls In Dwarka 9654467111 Escorts Service
 
While-For-loop in python used in college
While-For-loop in python used in collegeWhile-For-loop in python used in college
While-For-loop in python used in college
 
Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)
Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)
Call Us ➥97111√47426🤳Call Girls in Aerocity (Delhi NCR)
 
Call Girls in Saket 99530🔝 56974 Escort Service
Call Girls in Saket 99530🔝 56974 Escort ServiceCall Girls in Saket 99530🔝 56974 Escort Service
Call Girls in Saket 99530🔝 56974 Escort Service
 

APOC Pearls - Whirlwind Tour Through the Neo4j APOC Procedures Library

  • 1. APOC Pearls Michael Hunger Developer Relations Engineering, Neo4j Follow @mesirii APOC Unicorns
  • 2. All Images by TeeTurtle.com & Unstable Unicorns
  • 4. Extending Neo4j Neo4j Execution Engine User Defined Procedure Applications Bolt User Defined Procedures let you write custom code that is: • Written in any JVM language • Deployed to the Database • Accessed by applications via Cypher
  • 5. APOC History • My Unicorn Moment • 3.0 was about to have User Defined Procedures • Add the missing utilities • Grew quickly 50 - 150 - 450 • Active OSS project • Many contributors
  • 6.
  • 7. • Neo4j Sandbox • Neo4j Desktop • Neo4j Cloud Available On
  • 9. • Utilities & Converters • Data Integration • Import / Export • Graph Generation / Refactoring • Transactions / Jobs / TTL What's in the Box?
  • 10. • Videos • Documentation • Browser Guide • APOC Training • Neo4j Community Forum • apoc.help() Where can I learn more?
  • 11. If you learn one thing: apoc.help("keyword)")
  • 13. APOC Docs • installation instructions • videos • searchable overview table • detailed explaination • examples neo4j-contrib.github.io/neo4j-apoc-procedures
  • 15. The Pearls - That give you Superpowers 17
  • 17. • Relational / Cassandra • MongoDB, Couchbase, ElasticSearch • JSON, XML, CSV, XLS • Cypher, GraphML • ... Data Integration
  • 18. apoc.load.json • load json from web-apis and files • JSON Path • streaming JSON • compressed data https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_load_json
  • 19.
  • 20. WITH "https://api.stackexchange.com/2.2/questions?pagesize=100..." 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)) …
  • 22. Run large scale updates CALL apoc.periodic.iterate( 'MATCH (n:Person) RETURN n', 'SET n.name = n.firstName + " " + n.lastName', {batchSize:10000, parallel:true})
  • 23. Run large scale updates CALL apoc.periodic.iterate( 'LOAD CSV … AS row', 'MERGE (n:Node {id:row.id}) SET n.name = row.name', {batchSize:10000, concurrency:10})
  • 25. Text Functions - apoc.text.* indexOf, indexesOf split, replace, regexpGroups format capitalize, decapitalize random, lpad, rpad snakeCase, camelCase, upperCase charAt, hexCode base64, md5, sha1, https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_text_functions
  • 26. Collection Functions - apoc.coll.* sum, avg, min,max,stdev, zip, partition, pairs sort, toSet, contains, split indexOf, .different occurrences, frequencies, flatten disjunct, subtract, union, … set, insert, remove https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3.4/docs/overview.adoc#collection-functions
  • 27. Map Functions - apoc.map.* • .fromNodes, .fromPairs, .fromLists, .fromValues • .merge • .setKey,removeKey • .clean(map,[keys],[values]) • .groupBy https://github.com/neo4j-contrib/neo4j-apoc-procedures/blob/3.4/docs/overview.adoc#map-functions
  • 28. JSON - apoc.convert.* .toJson([1,2,3]) .fromJsonList('[1,2,3]') .fromJsonMap( '{"a":42,"b":"foo","c":[1,2,3]}') .toTree([paths],[lowerCaseRels=true]) .getJsonProperty(node,key) .setJsonProperty(node,key,complexValue)
  • 30. • .cloneNodes • .mergeNodes • .extractNode • .collapseNode • .categorize Relationship Modifications • .to(rel, endNode) • .from(rel, startNode) • .invert(rel) • .setType(rel, 'NEW-TYPE') Aggregation Function - apoc.refactor.*
  • 31. 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
  • 32. apoc.create.addLabels MATCH (n:Movie) CALL apoc.create.addLabels( id(n), [ n.genre ] ) YIELD node REMOVE node.genre RETURN node
  • 34. Triggers CALL apoc.trigger.add( name, statement,{phase:before/after}) • pause/resume/list/remove • Transaction-Event-Handler calls cypher statement • parameters: createdNodes, assignedNodeProperties, deletedNodes,... • utility functions to extract entities/properties from update-records • stores in graph properties
  • 36. enable in config: apoc.ttl.enabled=true Label :TTL apoc.date.expire(In)(node, time, unit) Creates Index on :TTL(ttl) Time To Live TTL
  • 37. background job (every 60s - configurable) that runs: MATCH (n:TTL) WHERE n.ttl > timestamp() WITH n LIMIT 1000 DET DELETE n Time To Live TTL
  • 39. Aggregation Function - apoc.agg.* • more efficient variants of collect(x)[a..b] • .nth,.first,.last,.slice • .median(x) • .percentiles(x,[0.5,0.9]) • .product(x) • .statistics() provides a full numeric statistic
  • 41. Graph Grouping MATCH (p:Person) set p.decade = b.born / 10; MATCH (p1:Person)-->()<--(p2:Person) WITH p1,p2,count(*) as c MERGE (p1)-[r:INTERACTED]-(p2) ON CREATE SET r.count = c CALL apoc.nodes.group(['Person'],['decade']) YIELD node, relationship RETURN *;
  • 43. apoc.custom.asProcedure/asFunction (name,statement, columns, params) • Register statements as real procedures & functions • 'custom' namespace prefix • Pass parameters, configure result columns • Stored in graph and distributed across cluster Custom Procedures (WIP)
  • 44. call apoc.custom.asProcedure('neighbours', 'MATCH (n:Person {name:$name})-->(nb) RETURN neighbour', [['neighbour','NODE']],[['name','STRING']]); call custom.neighbours('Joe') YIELD neighbour; Custom Procedures (WIP)
  • 52. Expand Operations Customized path expansion from start node(s) • Min/max traversals • Limit number of results • Optional (no rows removed if no results) • Choice of BFS/DFS expansion • Custom uniqueness (restrictions on visitations of nodes/rels) • Relationship and label filtering • Supports repeating sequences
  • 53. Expand Operations apoc.path.expand(startNode(s), relationshipFilter, labelFilter, minLevel, maxLevel) YIELD path • The original, when you don’t need much customization apoc.path.expandConfig(startNode(s), configMap) YIELD path • Most flexible, rich configuration map apoc.path.subgraphNodes(startNode(s), configMap) YIELD node • Only distinct nodes, don't care about paths apoc.path.spanningTree(startNode(s), configMap) YIELD path • Only one distinct path to each node apoc.path.subgraphAll(startNode(s), configMap) YIELD nodes, relationships • Only (collected) distinct nodes (and all rels between them)
  • 54. Config map values • minLevel: int • maxLevel: int • relationshipFilter • labelFilter • uniqueness: (‘RELATIONSHIP_PATH’, ’NODE_GLOBAL’, ‘NODE_PATH’, etc) • bfs: boolean, • filterStartNode: boolean • limit: int • optional: boolean • endNodes: [nodes] • terminatorNodes: [nodes] • sequence • beginSequenceAtStart: boolean
  • 55. Relationship Filter • '<ACTED_IN' - Incoming Rel • 'DIRECTED>' - Outgoing Rel • 'REVIEWED' - Any direction • '<ACTED_IN | DIRECTED> | REVIEWED' - Multiple, in varied directions • You can't do that with Cypher -[ACTED_IN|DIRECTED|REVIEWED]->
  • 56. Label Filter What is/isn't allowed during expansion, and what is/isn't returned • '-Director' – Blacklist, not allowed in path • '+Person' –Whitelist, only allowed in path (no whitelist = all allowed) • '>Reviewer' – End node, only return these, and continue expansion • '/Actor:Producer' – Terminator node, only return these, stop expansion 'Person|Movie|-Director|>Reviewer|/Actor:Producer' – Combine them
  • 57. Sequences Repeating sequences of relationships, labels, or both. Uses labelFilter and relationshipFilter, just add commas Or use sequence for both together labelFilter:'Post | -Blocked, Reply, >Admin' relationshipFilter:'NEXT>,<FROM,POSTED>|REPLIED>' sequence:'Post |-Blocked, NEXT>, Reply, <FROM, >Admin, POSTED>| REPLIED>'
  • 58. End nodes / Terminator nodes What if we already have the nodes that should end the expansion? endNodes – like filter, but takes a collection of nodes (or ids) terminatorNodes – like filter (stop expand), but also takes a collection (whitelistNodes and blacklistNodes too! ) Can be used with labelFilter or sequence, but continue or include must be unanimous
  • 59. End nodes / Terminator nodes What if we already have the nodes that should end the expansion? endNodes – like filter, but takes a collection of nodes (or ids) terminatorNodes – like filter (stop expand), but also takes a collection (whitelistNodes and blacklistNodes too! ) Can be used with labelFilter or sequence, but continue or include must be unanimous
  • 61. Bolt Connector CALL apoc.bolt.execute(url, statement, params, config) YIELD row CALL apoc.bolt.load(url, statement, params, config) YIELD row call apoc.bolt.load("bolt://user:password@localhost:7687"," match(p:Person {name:{name}}) return p", {name:'Michael'}) supports bolt connector parameters returns: scalars, Maps (row), virtual nodes,rels,paths
  • 64. Turn "[1,2,3]" into a Cypher List in plain Cypher 66
  • 65. Turn JSON List into Cypher List with "[1,2,3]" as str with split(substring(str,1, length(str)-2),",") as numbers return [x IN numbers| toInteger(x)]
  • 72. Gephi Integration match path = (:Person)-[:ACTED_IN]->(:Movie) WITH path LIMIT 1000 with collect(path) as paths call apoc.gephi.add(null,'workspace0', paths) yield nodes, relationships, time return nodes, relationships, time incremental send to Gephi, needs Gephi Streaming extension
  • 76. apoc.cypher.run(fragment, params) apoc.cypher.doIt(fragment, params) apoc.cypher.runTimeboxed apoc.cypher.runFile(file or url,{config}) apoc.cypher.runSchemaFile(file or url,{config}) apoc.cypher.runMany('cypher;nstatements;',{params},{config}) apoc.cypher.mapParallel(fragment, params, list-to-parallelize) Cypher Execution
  • 77. Check out the other periodic procs Try apoc.periodic.iterate example 79
  • 80. Warmup • load page-cache • page-skipping • new implementation based on PageCache.* • nodes + rels + rel-groups • properties • string / array properties • index pages
  • 82. Monitoring • apoc.monitor.ids • apoc.monitor.kernel • apoc.monitor.store • apoc.monitor.tx • apoc.monitor.locks(minWaitTime long)
  • 84. Conditional Cypher Execution CALL apoc.[do.]when(condition, ifQuery, elseQuery, params) CALL apoc.[do.]case([condition, query, condition, query, …​], elseQuery, params)
  • 86. Graph Generation • apoc.generate.er(noNodes, noEdges, 'label', 'type') Erdos-Renyi model (uniform) • apoc.generate.ws(noNodes, degree, beta, 'label', 'type') Watts-Strogatz model (clusters) • apoc.generate.ba(noNodes, edgesPerNode, 'label', 'type') Barabasi-Albert model (preferential attachment • apoc.generate.complete(noNodes, 'label', 'type') • apoc.generate.simple([degrees], 'label', 'type')
  • 91. Export apoc.export.csv .all / .data / .query apoc.export.cypher apoc.export.graphml leaving off filename does stream cypher to client
  • 93. Data Creation CALL apoc.create.node(['Label'], {key:value,…​}) CALL apoc.create.nodes(['Label'], [{key:value,…​}]) CALL apoc.create.addLabels, .removeLabels CALL apoc.create.setProperty CALL apoc.create.setProperties CALL apoc.create.relationship(from,'TYPE',{key:value,…​}, to) CALL apoc.nodes.link([nodes],'REL_TYPE')
  • 95. Virtual Entities Function AND Procedure apoc.create.vNode(['Label'], {key:value,…​}) YIELD node apoc.create.vRelationship(from,TYPE,{key:value,…​}, to) apoc.create.vPattern({_labels:[Label],key:value},'TYPE', {key:value,…​}, {_labels:['LabelB'],key:value})
  • 96. Try apoc.date.* with datetime() text, coll, map, convert funcs 98
  • 98. Latest Releases Summer Release 3.4.0.2 (Aug 8) Spring Release 3.4.0.1 (May 16) Winter Release 3.3.0.2 (Feb 23)
  • 100. Latest Additions • apoc.diff graph • new text similarity functions • CSV loader based on neo4j- import format • apoc.load.xls • apoc.group.nodes • Accessor functions for (virtual) entities • S3 Support • HDFS Support • apoc.index.addNodeMap • apoc.path.create • apoc.path.slice • apoc.path.combine • apoc.text.code(codepoint) • stream apoc.export.cypher • apoc.coll.combinations(), apoc.coll.frequencies() 102
  • 101. TASK Which of these are you interested in? Ask / Try 103
  • 102. Procedures / Functions from Cypher CALL apoc.custom.asProcedure('answer','RETURN 42 as answer'); CALL custom.answer(); works also with parameters, and return columns declarations CALL apoc.custom.asFunction('answer','RETURN $input','long', [['input','number']]); RETURN custom.answer(42) as answer;
  • 103. 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
  • 105. Can be written in any JVM language
  • 109. How to build them Developer Manual
  • 110. Build a procedure or function you'd like start with the template repo github.com/neo4j-examples/neo4j-procedure-template 112
  • 111. User Defined Procedures User-defined procedures are ● @Procedure annotated, named Java Methods ○ default name: package + method ● take @Name'ed parameters (3.1. default values) ● return a Stream of value objects ● fields are turned into columns ● can use @Context injected GraphDatabaseService etc ● run within Transaction
  • 112. 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; } } }
  • 113. 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 } } } Deploy & Register in Neo4j Server via neo4j-harness Call & test via neo4j-java-driver
  • 114. Deploying User Defined Procedures Build or download (shadow) jar ● Drop jar-file into $NEO4J_HOME/plugins ● Restart server ● Procedure should be available ● Otherwise check neo4j.log / debug.log
  • 116. Useable in any Cypher expression or lightweight computation
  • 118. 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 ); } }
  • 119. 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 ); } }
  • 120. 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 ); } }
  • 121. 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(); } }
  • 123. Custom, efficient aggregations for Data Science and BI
  • 124. Aggregation Function In APOC • more efficient variants of collect(x)[a..b] • apoc.agg.nth, apoc.agg.first, apoc.agg.last, apoc.agg.slice • apoc.agg.median(x) • apoc.agg.percentiles(x,[0.5,0.9]) • apoc.agg.product(x) • apoc.agg.statistics() provides a full numeric statistic
  • 125. UNWIND ['abc', 'abcd', 'ab'] AS string RETURN example.longestString(string) => 'abcd'
  • 126. 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; } } }
  • 127. 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; } } }
  • 128. 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; } } }
  • 129. 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; } } }
  • 130. 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(); } }
  • 131. One Question / Comment from each!