SlideShare a Scribd company logo
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

Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...
Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...
Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...
Spark Summit
 
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Databricks
 
Building Robust ETL Pipelines with Apache Spark
Building Robust ETL Pipelines with Apache SparkBuilding Robust ETL Pipelines with Apache Spark
Building Robust ETL Pipelines with Apache Spark
Databricks
 
GraphFrames: DataFrame-based graphs for Apache® Spark™
GraphFrames: DataFrame-based graphs for Apache® Spark™GraphFrames: DataFrame-based graphs for Apache® Spark™
GraphFrames: DataFrame-based graphs for Apache® Spark™
Databricks
 
Physical Plans in Spark SQL
Physical Plans in Spark SQLPhysical Plans in Spark SQL
Physical Plans in Spark SQL
Databricks
 
Dive into PySpark
Dive into PySparkDive into PySpark
Dive into PySpark
Mateusz Buśkiewicz
 
Producer Performance Tuning for Apache Kafka
Producer Performance Tuning for Apache KafkaProducer Performance Tuning for Apache Kafka
Producer Performance Tuning for Apache Kafka
Jiangjie Qin
 
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Databricks
 
Spark Summit EU talk by Ted Malaska
Spark Summit EU talk by Ted MalaskaSpark Summit EU talk by Ted Malaska
Spark Summit EU talk by Ted Malaska
Spark Summit
 
Catalyst optimizer
Catalyst optimizerCatalyst optimizer
Catalyst optimizer
Ayub Mohammad
 
Simplifying Big Data Analytics with Apache Spark
Simplifying Big Data Analytics with Apache SparkSimplifying Big Data Analytics with Apache Spark
Simplifying Big Data Analytics with Apache SparkDatabricks
 
Sharding Methods for MongoDB
Sharding Methods for MongoDBSharding Methods for MongoDB
Sharding Methods for MongoDB
MongoDB
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in Python
Siddhi
 
Introduction to MLflow
Introduction to MLflowIntroduction to MLflow
Introduction to MLflow
Databricks
 
SeaweedFS introduction
SeaweedFS introductionSeaweedFS introduction
SeaweedFS introduction
chrislusf
 
Top 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsTop 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark Applications
Spark Summit
 
Deep Dive: Memory Management in Apache Spark
Deep Dive: Memory Management in Apache SparkDeep Dive: Memory Management in Apache Spark
Deep Dive: Memory Management in Apache Spark
Databricks
 
Web-Scale Graph Analytics with Apache® Spark™
Web-Scale Graph Analytics with Apache® Spark™Web-Scale Graph Analytics with Apache® Spark™
Web-Scale Graph Analytics with Apache® Spark™
Databricks
 
What is new in Apache Hive 3.0?
What is new in Apache Hive 3.0?What is new in Apache Hive 3.0?
What is new in Apache Hive 3.0?
DataWorks Summit
 
Achieve Blazing-Fast Ingest Speeds with Apache Arrow
Achieve Blazing-Fast Ingest Speeds with Apache ArrowAchieve Blazing-Fast Ingest Speeds with Apache Arrow
Achieve Blazing-Fast Ingest Speeds with Apache Arrow
Neo4j
 

What's hot (20)

Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...
Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...
Spark SQL: Another 16x Faster After Tungsten: Spark Summit East talk by Brad ...
 
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
Deep Dive into Spark SQL with Advanced Performance Tuning with Xiao Li & Wenc...
 
Building Robust ETL Pipelines with Apache Spark
Building Robust ETL Pipelines with Apache SparkBuilding Robust ETL Pipelines with Apache Spark
Building Robust ETL Pipelines with Apache Spark
 
GraphFrames: DataFrame-based graphs for Apache® Spark™
GraphFrames: DataFrame-based graphs for Apache® Spark™GraphFrames: DataFrame-based graphs for Apache® Spark™
GraphFrames: DataFrame-based graphs for Apache® Spark™
 
Physical Plans in Spark SQL
Physical Plans in Spark SQLPhysical Plans in Spark SQL
Physical Plans in Spark SQL
 
Dive into PySpark
Dive into PySparkDive into PySpark
Dive into PySpark
 
Producer Performance Tuning for Apache Kafka
Producer Performance Tuning for Apache KafkaProducer Performance Tuning for Apache Kafka
Producer Performance Tuning for Apache Kafka
 
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
Improving SparkSQL Performance by 30%: How We Optimize Parquet Pushdown and P...
 
Spark Summit EU talk by Ted Malaska
Spark Summit EU talk by Ted MalaskaSpark Summit EU talk by Ted Malaska
Spark Summit EU talk by Ted Malaska
 
Catalyst optimizer
Catalyst optimizerCatalyst optimizer
Catalyst optimizer
 
Simplifying Big Data Analytics with Apache Spark
Simplifying Big Data Analytics with Apache SparkSimplifying Big Data Analytics with Apache Spark
Simplifying Big Data Analytics with Apache Spark
 
Sharding Methods for MongoDB
Sharding Methods for MongoDBSharding Methods for MongoDB
Sharding Methods for MongoDB
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in Python
 
Introduction to MLflow
Introduction to MLflowIntroduction to MLflow
Introduction to MLflow
 
SeaweedFS introduction
SeaweedFS introductionSeaweedFS introduction
SeaweedFS introduction
 
Top 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsTop 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark Applications
 
Deep Dive: Memory Management in Apache Spark
Deep Dive: Memory Management in Apache SparkDeep Dive: Memory Management in Apache Spark
Deep Dive: Memory Management in Apache Spark
 
Web-Scale Graph Analytics with Apache® Spark™
Web-Scale Graph Analytics with Apache® Spark™Web-Scale Graph Analytics with Apache® Spark™
Web-Scale Graph Analytics with Apache® Spark™
 
What is new in Apache Hive 3.0?
What is new in Apache Hive 3.0?What is new in Apache Hive 3.0?
What is new in Apache Hive 3.0?
 
Achieve Blazing-Fast Ingest Speeds with Apache Arrow
Achieve Blazing-Fast Ingest Speeds with Apache ArrowAchieve Blazing-Fast Ingest Speeds with Apache Arrow
Achieve Blazing-Fast Ingest Speeds with Apache Arrow
 

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
 
Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
How to Begin Developing Ruby Core
How to Begin Developing Ruby CoreHow to Begin Developing Ruby Core
How to Begin Developing Ruby Core
Hiroshi 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 Go
Matt 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 clojure
Abbas Raza
 
Ansible with oci
Ansible with ociAnsible with oci
Ansible with oci
DonghuKIM2
 
Intro To Node.js
Intro To Node.jsIntro To Node.js
Intro To Node.js
Chris Cowan
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
Guillaume 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.js
orkaplan
 
Get to know PostgreSQL!
Get to know PostgreSQL!Get to know PostgreSQL!
Get to know PostgreSQL!
Oddbjørn Steffensen
 
Logstash
LogstashLogstash
Logstash
琛琳 饶
 
Postgres Vienna DB Meetup 2014
Postgres Vienna DB Meetup 2014Postgres Vienna DB Meetup 2014
Postgres Vienna DB Meetup 2014
Michael 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 Wolff
JAX 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 App
Pebble 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-C
Alexis 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.pdf
jexp
 
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
jexp
 
Looming Marvelous - Virtual Threads in Java
Looming Marvelous - Virtual Threads in JavaLooming Marvelous - Virtual Threads in Java
Looming Marvelous - Virtual Threads in Java
jexp
 
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
jexp
 
Neo4j Connector Apache Spark FiNCENFiles
Neo4j Connector Apache Spark FiNCENFilesNeo4j Connector Apache Spark FiNCENFiles
Neo4j Connector Apache Spark FiNCENFiles
jexp
 
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
jexp
 
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 GraalVM
jexp
 
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
jexp
 
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 Edition
jexp
 
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-Development
jexp
 
A whirlwind tour of graph databases
A whirlwind tour of graph databasesA whirlwind tour of graph databases
A whirlwind tour of graph databases
jexp
 
Practical Graph Algorithms with Neo4j
Practical Graph Algorithms with Neo4jPractical Graph Algorithms with Neo4j
Practical Graph Algorithms with Neo4j
jexp
 
A Game of Data and GraphQL
A Game of Data and GraphQLA Game of Data and GraphQL
A Game of Data and GraphQL
jexp
 
Querying Graphs with GraphQL
Querying Graphs with GraphQLQuerying Graphs with GraphQL
Querying Graphs with GraphQL
jexp
 
Graphs & Neo4j - Past Present Future
Graphs & Neo4j - Past Present FutureGraphs & Neo4j - Past Present Future
Graphs & Neo4j - Past Present Future
jexp
 
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 metrics
jexp
 

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

做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样
做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样
做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样
axoqas
 
Ch03-Managing the Object-Oriented Information Systems Project a.pdf
Ch03-Managing the Object-Oriented Information Systems Project a.pdfCh03-Managing the Object-Oriented Information Systems Project a.pdf
Ch03-Managing the Object-Oriented Information Systems Project a.pdf
haila53
 
Criminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdfCriminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdf
Criminal IP
 
Innovative Methods in Media and Communication Research by Sebastian Kubitschk...
Innovative Methods in Media and Communication Research by Sebastian Kubitschk...Innovative Methods in Media and Communication Research by Sebastian Kubitschk...
Innovative Methods in Media and Communication Research by Sebastian Kubitschk...
correoyaya
 
Opendatabay - Open Data Marketplace.pptx
Opendatabay - Open Data Marketplace.pptxOpendatabay - Open Data Marketplace.pptx
Opendatabay - Open Data Marketplace.pptx
Opendatabay
 
The affect of service quality and online reviews on customer loyalty in the E...
The affect of service quality and online reviews on customer loyalty in the E...The affect of service quality and online reviews on customer loyalty in the E...
The affect of service quality and online reviews on customer loyalty in the E...
jerlynmaetalle
 
一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单
一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单
一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单
ewymefz
 
【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】
【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】
【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】
NABLAS株式会社
 
Adjusting primitives for graph : SHORT REPORT / NOTES
Adjusting primitives for graph : SHORT REPORT / NOTESAdjusting primitives for graph : SHORT REPORT / NOTES
Adjusting primitives for graph : SHORT REPORT / NOTES
Subhajit Sahu
 
Jpolillo Amazon PPC - Bid Optimization Sample
Jpolillo Amazon PPC - Bid Optimization SampleJpolillo Amazon PPC - Bid Optimization Sample
Jpolillo Amazon PPC - Bid Optimization Sample
James Polillo
 
Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...
Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...
Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...
Subhajit Sahu
 
一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单
一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单
一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单
vcaxypu
 
一比一原版(YU毕业证)约克大学毕业证成绩单
一比一原版(YU毕业证)约克大学毕业证成绩单一比一原版(YU毕业证)约克大学毕业证成绩单
一比一原版(YU毕业证)约克大学毕业证成绩单
enxupq
 
Q1’2024 Update: MYCI’s Leap Year Rebound
Q1’2024 Update: MYCI’s Leap Year ReboundQ1’2024 Update: MYCI’s Leap Year Rebound
Q1’2024 Update: MYCI’s Leap Year Rebound
Oppotus
 
Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...
Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...
Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...
John Andrews
 
哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样
哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样
哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样
axoqas
 
SOCRadar Germany 2024 Threat Landscape Report
SOCRadar Germany 2024 Threat Landscape ReportSOCRadar Germany 2024 Threat Landscape Report
SOCRadar Germany 2024 Threat Landscape Report
SOCRadar
 
Criminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdfCriminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdf
Criminal IP
 
Business update Q1 2024 Lar España Real Estate SOCIMI
Business update Q1 2024 Lar España Real Estate SOCIMIBusiness update Q1 2024 Lar España Real Estate SOCIMI
Business update Q1 2024 Lar España Real Estate SOCIMI
AlejandraGmez176757
 
一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单
一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单
一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单
nscud
 

Recently uploaded (20)

做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样
做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样
做(mqu毕业证书)麦考瑞大学毕业证硕士文凭证书学费发票原版一模一样
 
Ch03-Managing the Object-Oriented Information Systems Project a.pdf
Ch03-Managing the Object-Oriented Information Systems Project a.pdfCh03-Managing the Object-Oriented Information Systems Project a.pdf
Ch03-Managing the Object-Oriented Information Systems Project a.pdf
 
Criminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdfCriminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdf
 
Innovative Methods in Media and Communication Research by Sebastian Kubitschk...
Innovative Methods in Media and Communication Research by Sebastian Kubitschk...Innovative Methods in Media and Communication Research by Sebastian Kubitschk...
Innovative Methods in Media and Communication Research by Sebastian Kubitschk...
 
Opendatabay - Open Data Marketplace.pptx
Opendatabay - Open Data Marketplace.pptxOpendatabay - Open Data Marketplace.pptx
Opendatabay - Open Data Marketplace.pptx
 
The affect of service quality and online reviews on customer loyalty in the E...
The affect of service quality and online reviews on customer loyalty in the E...The affect of service quality and online reviews on customer loyalty in the E...
The affect of service quality and online reviews on customer loyalty in the E...
 
一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单
一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单
一比一原版(UofM毕业证)明尼苏达大学毕业证成绩单
 
【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】
【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】
【社内勉強会資料_Octo: An Open-Source Generalist Robot Policy】
 
Adjusting primitives for graph : SHORT REPORT / NOTES
Adjusting primitives for graph : SHORT REPORT / NOTESAdjusting primitives for graph : SHORT REPORT / NOTES
Adjusting primitives for graph : SHORT REPORT / NOTES
 
Jpolillo Amazon PPC - Bid Optimization Sample
Jpolillo Amazon PPC - Bid Optimization SampleJpolillo Amazon PPC - Bid Optimization Sample
Jpolillo Amazon PPC - Bid Optimization Sample
 
Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...
Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...
Algorithmic optimizations for Dynamic Levelwise PageRank (from STICD) : SHORT...
 
一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单
一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单
一比一原版(RUG毕业证)格罗宁根大学毕业证成绩单
 
一比一原版(YU毕业证)约克大学毕业证成绩单
一比一原版(YU毕业证)约克大学毕业证成绩单一比一原版(YU毕业证)约克大学毕业证成绩单
一比一原版(YU毕业证)约克大学毕业证成绩单
 
Q1’2024 Update: MYCI’s Leap Year Rebound
Q1’2024 Update: MYCI’s Leap Year ReboundQ1’2024 Update: MYCI’s Leap Year Rebound
Q1’2024 Update: MYCI’s Leap Year Rebound
 
Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...
Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...
Chatty Kathy - UNC Bootcamp Final Project Presentation - Final Version - 5.23...
 
哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样
哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样
哪里卖(usq毕业证书)南昆士兰大学毕业证研究生文凭证书托福证书原版一模一样
 
SOCRadar Germany 2024 Threat Landscape Report
SOCRadar Germany 2024 Threat Landscape ReportSOCRadar Germany 2024 Threat Landscape Report
SOCRadar Germany 2024 Threat Landscape Report
 
Criminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdfCriminal IP - Threat Hunting Webinar.pdf
Criminal IP - Threat Hunting Webinar.pdf
 
Business update Q1 2024 Lar España Real Estate SOCIMI
Business update Q1 2024 Lar España Real Estate SOCIMIBusiness update Q1 2024 Lar España Real Estate SOCIMI
Business update Q1 2024 Lar España Real Estate SOCIMI
 
一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单
一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单
一比一原版(CBU毕业证)不列颠海角大学毕业证成绩单
 

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!