SlideShare a Scribd company logo
1 of 80
Download to read offline
Graph Modeling
Tips and Tricks
Mark Needham @markhneedham
Introducing our data set...
meetup.com’s recommendations
Recommendation queries
‣ Several different types
• groups to join
• topics to follow
• events to attend
‣ As a user of meetup.com trying to find
groups to join and events to attend
How will this talk be structured?
Find similar groups to Neo4j
As a member of the Neo4j London group
I want to find other similar meetup groups
So that I can join those groups
What makes groups similar?
As a member of the Neo4j London group
I want to find other similar meetup groups
So that I can join those groups
Find similar groups to Neo4j
As a member of the Neo4j London group
I want to find other similar meetup groups
So that I can join those groups
Nodes
As a member of the Neo4j London group
I want to find other similar meetup groups
So that I can join those groups
Relationships
As a member of the Neo4j London group
I want to find other similar meetup groups
So that I can join those groups
Labels
As a member of the Neo4j London group
I want to find other similar meetup groups
So that I can join those groups
Properties
Find similar groups to Neo4j
MATCH (group:Group {name: "Neo4j - London User Group"})
-[:HAS_TOPIC]->(topic)<-[:HAS_TOPIC]-(otherGroup)
RETURN otherGroup.name,
COUNT(topic) AS topicsInCommon,
COLLECT(topic.name) AS topics
ORDER BY topicsInCommon DESC, otherGroup.name
LIMIT 10
Find similar groups to Neo4j
Tip: Model incrementally
‣ Build the model for the question we need
to answer now then move onto the next
question
I’m already a member of these!
What other data can we get?
Exclude groups I’m a member of
As a member of the Neo4j London group
I want to find other similar meetup groups
that I’m not already a member of
So that I can join those groups
Exclude groups I’m a member of
As a member of the Neo4j London group
I want to find other similar meetup groups
that I’m not already a member of
So that I can join those groups
Exclude groups I’m a member of
MATCH (group:Group {name: "Neo4j - London User Group"})
-[:HAS_TOPIC]->(topic)<-[:HAS_TOPIC]-(otherGroup:Group)
RETURN otherGroup.name,
COUNT(topic) AS topicsInCommon,
EXISTS((:Member {name: "Mark Needham"})
-[:MEMBER_OF]->(otherGroup)) AS alreadyMember,
COLLECT(topic.name) AS topics
ORDER BY topicsInCommon DESC
LIMIT 10
Exclude groups I’m a member of
Exclude groups I’m a member of
MATCH (group:Group {name: "Neo4j - London User Group"})
-[:HAS_TOPIC]->(topic)<-[:HAS_TOPIC]-(otherGroup:Group)
WHERE NOT( (:Member {name: "Mark Needham"})
-[:MEMBER_OF]->(otherGroup) )
RETURN otherGroup.name,
COUNT(topic) AS topicsInCommon,
COLLECT(topic.name) AS topics
ORDER BY topicsInCommon DESC
LIMIT 10
Exclude groups I’m a member of
Find my similar groups
As a member of several meetup groups
I want to find other similar meetup groups
that I’m not already a member of
So that I can join those groups
Find my similar groups
As a member of several meetup groups
I want to find other similar meetup groups
that I’m not already a member of
So that I can join those groups
Find my similar groups
MATCH (member:Member {name: "Mark Needham"})
-[:INTERESTED_IN]->(topic),
(member)-[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic)
WITH member, topic, COUNT(*) AS score
MATCH (topic)<-[:HAS_TOPIC]-(otherGroup)
WHERE NOT (member)-[:MEMBER_OF]->(otherGroup)
RETURN otherGroup.name,
COLLECT(topic.name),
SUM(score) as score
ORDER BY score DESC
Find my similar groups
Find Jonny’s similar groups
Oops...Jonny has no interests!
What is Jonny interested in?
As a member of several meetup groups
I want to find other similar meetup groups
that I’m not already a member of
So that I can join those groups
INTERESTED_IN?
What is Jonny interested in?
There’s an implicit INTERESTED_IN relationship
between the topics of groups I belong to but
don’t express an interest in. Let’s make it explicit
P
G
T
MEMBER_OF
HAS_TOPIC
P
G
T
MEMBER_OF
HAS_TOPIC
INTERESTED_IN
What is Jonny interested in?
MATCH (m:Member)-[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic)
WITH m, topic, COUNT(*) AS times
WHERE times > 3
MERGE (m)-[:INTERESTED_IN]->(topic)
What is Jonny interested in?
Tip: Make the implicit explicit
‣ Fill in the missing links in the graph
‣ You could run this type of query once a day
during a quiet period
‣ On bigger graphs we’d run it in
batches to avoid loading the
whole database into memory
Find next group people join
As a member of a meetup group
I want to find out which meetup groups
other people join after this one
So that I can join those groups
Find next group people join
MATCH (group:Group {name: "Neo4j - London User Group"})
<-[membership:MEMBER_OF]-(member),
(member)-[otherMembership:MEMBER_OF]->(otherGroup)
WHERE membership.joined < otherMembership.joined
WITH member, otherGroup
ORDER BY otherMembership.joined
WITH member, COLLECT(otherGroup)[0] AS nextGroup
RETURN nextGroup.name, COUNT(*) AS times
ORDER BY times DESC
Find next group people join
It feels a bit clunky...
MATCH (group:Group {name: "Neo4j - London User Group"})
<-[membership:MEMBER_OF]-(member),
(member)-[otherMembership:MEMBER_OF]->(otherGroup)
WHERE membership.joined < otherMembership.joined
WITH member, otherGroup
ORDER BY otherMembership.joined
WITH member, COLLECT(otherGroup)[0] AS nextGroup
RETURN nextGroup.name, COUNT(*) AS times
ORDER BY times DESC
‣ We have to scan through all the MEMBER_OF
relationships to find the one we want
‣ It might make our lives easier if we made
membership a first class citizen of the domain
Facts can become nodes
Facts can become nodes
Refactor to facts
MATCH (member:Member)-[rel:MEMBER_OF]->(group)
MERGE (membership:Membership {id: member.id + "_" + group.id})
SET membership.joined = rel.joined
MERGE (member)-[:HAS_MEMBERSHIP]->(membership)
MERGE (membership)-[:OF_GROUP]->(group)
Refactor to facts
MATCH (member:Member)-[:HAS_MEMBERSHIP]->(membership)
WITH member, membership ORDER BY member.id, membership.joined
WITH member, COLLECT(membership) AS memberships
UNWIND RANGE(0,SIZE(memberships) - 2) as idx
WITH memberships[idx] AS m1, memberships[idx+1] AS m2
MERGE (m1)-[:NEXT]->(m2)
Find next group people join
MATCH (group:Group {name: "Neo4j - London User Group"})
<-[:OF_GROUP]-(membership)-[:NEXT]->(nextMembership),
(membership)<-[:HAS_MEMBERSHIP]-(member:Member)
-[:HAS_MEMBERSHIP]->(nextMembership),
(nextMembership)-[:OF_GROUP]->(nextGroup)
RETURN nextGroup.name, COUNT(*) AS times
ORDER BY times DESC
Comparing the approaches
vs
MATCH (group:Group {name: "Neo4j - London User Group"})
<-[membership:MEMBER_OF]-(member),
(member)-[otherMembership:MEMBER_OF]->(otherGroup)
WITH member, membership, otherMembership, otherGroup
ORDER BY member.id, otherMembership.joined
WHERE membership.joined < otherMembership.joined
WITH member, membership, COLLECT(otherGroup)[0] AS nextGroup
RETURN nextGroup.name, COUNT(*) AS times
ORDER BY times DESC
MATCH (group:Group {name: "Neo4j - London User Group"})
<-[:OF_GROUP]-(membership)-[:NEXT]->(nextMembership),
(membership)<-[:HAS_MEMBERSHIP]-(member:Member)
-[:HAS_MEMBERSHIP]->(nextMembership),
(nextMembership)-[:OF_GROUP]->(nextGroup)
RETURN nextGroup.name, COUNT(*) AS times
ORDER BY times DESC
How do I profile a query?
‣ EXPLAIN
• shows the execution plan without actually
executing it or returning any results.
‣ PROFILE
• executes the statement and returns the results
along with profiling information.
45
Neo4j’s longest plan (so far…)
46
Neo4j’s longest plan (so far…)
47
Neo4j’s longest plan (so far…)
48
What is our goal?
At a high level, the goal is
simple: get the number of
db hits down.
49
an abstract unit of storage
engine work.
What is a database hit?
“
”
50
Comparing the approaches
Cypher version: CYPHER 2.3,
planner: COST.
111656 total db hits in 330 ms.
vs
Cypher version: CYPHER 2.3,
planner: COST.
23650 total db hits in 60 ms.
Tip: Profile your queries
‣ Spike the different models and see which
one performs the best
Should we keep both models?
We could but when we add, edit or remove a membership
we’d have to keep both graph structures in sync.
Adding a group membership
WITH "Mark Needham" AS memberName,
"Neo4j - London User Group" AS groupName,
timestamp() AS now
MATCH (group:Group {name: groupName})
MATCH (member:Member {name: memberName})
MERGE (member)-[memberOfRel:MEMBER_OF]->(group)
ON CREATE SET memberOfRel.time = now
MERGE (membership:Membership {id: member.id + "_" + group.id})
ON CREATE SET membership.joined = now
MERGE (member)-[:HAS_MEMBERSHIP]->(membership)
MERGE (membership)-[:OF_GROUP]->(group)
Removing a group membership
WITH "Mark Needham" AS memberName,
"Neo4j - London User Group" AS groupName,
timestamp() AS now
MATCH (group:Group {name: groupName})
MATCH (member:Member {name: memberName})
MATCH (member)-[memberOfRel:MEMBER_OF]->(group)
MATCH (membership:Membership {id: member.id + "_" + group.id})
MATCH (member)-[hasMembershipRel:HAS_MEMBERSHIP]->(membership)
MATCH (membership)-[ofGroupRel:OF_GROUP]->(group)
DELETE memberOfRel, hasMembershipRel, ofGroupRel, membership
Let’s delete MEMBER_OF then...
...not so fast!
As a member of several meetup groups
I want to find other similar meetup groups
that I’m not already a member of
So that I can join those groups
Why not delete MEMBER_OF?
MATCH (member:Member {name: "Mark Needham"})
-[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic)
WITH member, topic, COUNT(*) AS score
MATCH (topic)<-[:HAS_TOPIC]-(otherGroup)
WHERE NOT (member)-[:MEMBER_OF]->(otherGroup)
RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score
ORDER BY score DESC
MATCH (member:Member {name: "Mark Needham"})
-[:HAS_MEMBERSHIP]->()-[:OF_GROUP]->(group:Group)-[:HAS_TOPIC]->(topic)
WITH member, topic, COUNT(*) AS score
MATCH (topic)<-[:HAS_TOPIC]-(otherGroup)
WHERE NOT (member)-[:HAS_MEMBERSHIP]->(:Membership)-[:OF_GROUP]->(otherGroup:Group)
RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score
ORDER BY score DESC
Why not delete MEMBER_OF?
MATCH (member:Member {name: "Mark Needham"})
-[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic)
WITH member, topic, COUNT(*) AS score
MATCH (topic)<-[:HAS_TOPIC]-(otherGroup)
WHERE NOT (member)-[:MEMBER_OF]->(otherGroup)
RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score
ORDER BY score DESC
MATCH (member:Member {name: "Mark Needham"})
-[:HAS_MEMBERSHIP]->()-[:OF_GROUP]->(group:Group)-[:HAS_TOPIC]->(topic)
WITH member, topic, COUNT(*) AS score
MATCH (topic)<-[:HAS_TOPIC]-(otherGroup)
WHERE NOT (member)-[:HAS_MEMBERSHIP]->(:Membership)-[:OF_GROUP]->(otherGroup:Group)
RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score
ORDER BY score DESC
433318 total db hits in 485 ms.
83268 total db hits in 117 ms.
Tip: Maintaining multiple models
‣ Different models perform better for
different queries but worse for others
‣ Optimising for reads may mean we pay a
write and maintenance penalty
What about events?
Events in my groups
As a member of several meetup groups who
has previously attended events
I want to find other events hosted by those
groups
So that I can attend those events
Events in my groups
As a member of several meetup
groups who has previously
attended events
I want to find other events
hosted by those groups
So that I can attend those events
WITH 24.0*60*60*1000 AS oneDay
MATCH (member:Member {name: "Mark Needham"}),
(member)-[:MEMBER_OF]->(group),
(group)-[:HOSTED_EVENT]->(futureEvent)
WHERE futureEvent.time >= timestamp()
AND NOT (member)-[:RSVPD]->(futureEvent)
RETURN group.name, futureEvent.name,
round((futureEvent.time - timestamp()) / oneDay) AS days
ORDER BY days
LIMIT 10
Events in my groups
Events in my groups
+ previous events attended
WITH 24.0*60*60*1000 AS oneDay
MATCH (member:Member {name: "Mark Needham"})
MATCH (futureEvent:Event)
WHERE futureEvent.time >= timestamp() AND NOT (member)-[:RSVPD]->(futureEvent)
MATCH (futureEvent)<-[:HOSTED_EVENT]-(group)
WITH oneDay, group, futureEvent, member, EXISTS((group)<-[:MEMBER_OF]-(member)) AS isMember
OPTIONAL MATCH (member)-[rsvp:RSVPD {response: "yes"}]->(pastEvent)<-[:HOSTED_EVENT]-(group)
WHERE pastEvent.time < timestamp()
RETURN group.name,
futureEvent.name,
isMember,
COUNT(rsvp) AS previousEvents,
round((futureEvent.time - timestamp()) / oneDay) AS days
ORDER BY days, previousEvents DESC
+ previous events attended
RSVPD_YES vs RSVPD
I was curious whether refactoring
RSVPD {response: "yes"} to RSVPD_YES would have
any impact as Neo4j is optimised for querying
by unique relationship types.
Refactor to specific relationships
MATCH (m:Member)-[rsvp:RSVPD {response:"yes"}]->(event)
MERGE (m)-[rsvpYes:RSVPD_YES {id: rsvp.id}]->(event)
ON CREATE SET rsvpYes.created = rsvp.created,
rsvpYes.lastModified = rsvp.lastModified;
MATCH (m:Member)-[rsvp:RSVPD {response:"no"}]->(event)
MERGE (m)-[rsvpYes:RSVPD_NO {id: rsvp.id}]->(event)
ON CREATE SET rsvpYes.created = rsvp.created,
rsvpYes.lastModified = rsvp.lastModified;
RSVPD_YES vs RSVPD
RSVPD {response: "yes"}
vs
RSVPD_YES
Cypher version: CYPHER 2.3,
planner: COST.
688635 total db hits in 232 ms.
Cypher version: CYPHER 2.3,
planner: COST.
559866 total db hits in 207 ms.
Why would we keep RSVPD?
MATCH (m:Member)-[r:RSVPD]->(event)<-[:HOSTED_EVENT]-(group)
WHERE m.name = "Mark Needham"
RETURN event, group, r
MATCH (m:Member)-[r:RSVPD_YES|:RSVPD_NO|:RSVPD_WAITLIST]->(event),
(event)<-[:HOSTED_EVENT]-(group)
WHERE m.name = "Mark Needham"
RETURN event, group, r
Tip: Specific relationships
‣ Neo4j is optimised for querying by unique
relationship types…
‣ ...but sometimes we pay a query
maintenance cost to achieve this
+ events my friends are attending
There’s an implicit FRIENDS relationship
between people who attended the same events.
Let’s make it explicit.
M
E
M
RSVPD
RSVPD
FRIENDS
M
E
M
RSVPD
RSVPD
+ events my friends are attending
MATCH (m1:Member)
WHERE NOT m1:Processed
WITH m1 LIMIT {limit}
MATCH (m1)-[:RSVP_YES]->(event:Event)<-[:RSVP_YES]-(m2:Member)
WITH m1, m2, COLLECT(event) AS events, COUNT(*) AS times
WHERE times >= 5
WITH m1, m2, times, [event IN events | SIZE((event)<-[:RSVP_YES]-())] AS attendances
WITH m1, m2, REDUCE(score = 0.0, a IN attendances | score + (1.0 / a)) AS score
MERGE (m1)-[friendsRel:FRIENDS]-(m2)
SET friendsRel.score = row.score
Bidirectional relationships
‣ You may have noticed that we didn’t specify a
direction when creating the relationship
MERGE (m1)-[:FRIENDS]-(m2)
‣ FRIENDS is a bidirectional relationship. We only
need to create it once between two people.
‣ We ignore the direction when querying
+ events my friends are attending
WITH 24.0*60*60*1000 AS oneDay
MATCH (member:Member {name: "Mark Needham"})
MATCH (futureEvent:Event)
WHERE futureEvent.time >= timestamp() AND NOT (member)-[:RSVPD]->(futureEvent)
MATCH (futureEvent)<-[:HOSTED_EVENT]-(group)
WITH oneDay, group, futureEvent, member, EXISTS((group)<-[:MEMBER_OF]-(member)) AS isMember
OPTIONAL MATCH (member)-[rsvp:RSVPD {response: "yes"}]->(pastEvent)<-[:HOSTED_EVENT]-(group)
WHERE pastEvent.time < timestamp()
WITH oneDay, group, futureEvent, member, isMember, COUNT(rsvp) AS previousEvents
OPTIONAL MATCH (futureEvent)<-[:HOSTED_EVENT]-()-[:HAS_TOPIC]->(topic)<-[:INTERESTED_IN]-(member)
WITH oneDay, group, futureEvent, member, isMember, previousEvents, COUNT(topic) AS topics
OPTIONAL MATCH (member)-[:FRIENDS]-(:Member)-[rsvpYes:RSVP_YES]->(futureEvent)
RETURN group.name, futureEvent.name, isMember, round((futureEvent.time - timestamp()) / oneDay) AS days,
previousEvents, topics, COUNT(rsvpYes) AS friendsGoing
ORDER BY days, friendsGoing DESC, previousEvents DESC
LIMIT 15
+ events my friends are attending
Tip: Bidirectional relationships
‣ Some relationships are bidirectional in nature
‣ Neo4j always stores relationships with a
direction but we can choose to ignore that
when we query
tl;dr
‣ Model incrementally
‣ Always profile your queries
‣ Consider making the implicit explicit…
• ...but beware the maintenance cost
‣ Be specific with relationship types
‣ Ignore direction for bidirectional relationships
That’s all for today!
Questions? :-)
Mark Needham @markhneedham
https://github.com/neo4j-meetups/modeling-worked-example

More Related Content

Viewers also liked

GraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia Powers
GraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia PowersGraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia Powers
GraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia PowersNeo4j
 
GraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas Suravarapu
GraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas SuravarapuGraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas Suravarapu
GraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas SuravarapuNeo4j
 
GraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark Needham
GraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark NeedhamGraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark Needham
GraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark NeedhamNeo4j
 
Slides from GraphDay Santa Clara
Slides from GraphDay Santa ClaraSlides from GraphDay Santa Clara
Slides from GraphDay Santa ClaraNeo4j
 
Intro to Cypher for the SQL Developer
Intro to Cypher for the SQL DeveloperIntro to Cypher for the SQL Developer
Intro to Cypher for the SQL DeveloperNeo4j
 
GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...
GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...
GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...Neo4j
 
GraphTalk Berlin - Neo4j und FirstSpirit
GraphTalk Berlin - Neo4j und FirstSpiritGraphTalk Berlin - Neo4j und FirstSpirit
GraphTalk Berlin - Neo4j und FirstSpiritNeo4j
 
GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...
GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...
GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...Neo4j
 
GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...
GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...
GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...Neo4j
 
GraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin Nussbaum
GraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin NussbaumGraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin Nussbaum
GraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin NussbaumNeo4j
 
GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...
GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...
GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...Neo4j
 
GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...
GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...
GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...Neo4j
 
GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...
GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...
GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...Neo4j
 
GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...
GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...
GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...Neo4j
 
GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...
GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...
GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...Neo4j
 
Neo4j GraphTalks - Semantische Netze
Neo4j GraphTalks - Semantische NetzeNeo4j GraphTalks - Semantische Netze
Neo4j GraphTalks - Semantische NetzeNeo4j
 
Neo4j GraphTalks - Einführung in Graphdatenbanken
Neo4j GraphTalks - Einführung in GraphdatenbankenNeo4j GraphTalks - Einführung in Graphdatenbanken
Neo4j GraphTalks - Einführung in GraphdatenbankenNeo4j
 
GraphTalk Berlin - Einführung in Graphdatenbanken
GraphTalk Berlin - Einführung in GraphdatenbankenGraphTalk Berlin - Einführung in Graphdatenbanken
GraphTalk Berlin - Einführung in GraphdatenbankenNeo4j
 
Introducing Neo4j 3.1: New Security and Clustering Architecture
Introducing Neo4j 3.1: New Security and Clustering Architecture Introducing Neo4j 3.1: New Security and Clustering Architecture
Introducing Neo4j 3.1: New Security and Clustering Architecture Neo4j
 
GraphTalks Hamburg - Einführung in Graphdatenbanken
GraphTalks Hamburg - Einführung in GraphdatenbankenGraphTalks Hamburg - Einführung in Graphdatenbanken
GraphTalks Hamburg - Einführung in GraphdatenbankenNeo4j
 

Viewers also liked (20)

GraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia Powers
GraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia PowersGraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia Powers
GraphConnect Europe 2016 - Who Cares What Beyonce Ate for Lunch? - Alicia Powers
 
GraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas Suravarapu
GraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas SuravarapuGraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas Suravarapu
GraphConnect Europe 2016 - Faster Lap Times with Neo4j - Srinivas Suravarapu
 
GraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark Needham
GraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark NeedhamGraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark Needham
GraphConnect Europe 2016 - Tuning Your Cypher - Petra Selmer, Mark Needham
 
Slides from GraphDay Santa Clara
Slides from GraphDay Santa ClaraSlides from GraphDay Santa Clara
Slides from GraphDay Santa Clara
 
Intro to Cypher for the SQL Developer
Intro to Cypher for the SQL DeveloperIntro to Cypher for the SQL Developer
Intro to Cypher for the SQL Developer
 
GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...
GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...
GraphConnect Europe 2016 - NoSQL Polyglot Persistence: Tools and Integrations...
 
GraphTalk Berlin - Neo4j und FirstSpirit
GraphTalk Berlin - Neo4j und FirstSpiritGraphTalk Berlin - Neo4j und FirstSpirit
GraphTalk Berlin - Neo4j und FirstSpirit
 
GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...
GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...
GraphConnect Europe 2016 - Digitalization and Optimizing Business Performance...
 
GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...
GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...
GraphConnect Europe 2016 - Enterprise Data Integration with a new JDBC Driver...
 
GraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin Nussbaum
GraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin NussbaumGraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin Nussbaum
GraphConnect Europe 2016 - Securely Deploying Neo4j into AWS - Benjamin Nussbaum
 
GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...
GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...
GraphConnect Europe 2016 - IoT - where do Graphs fit with Business Requiremen...
 
GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...
GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...
GraphConnect Europe 2016 - Building Consumer Trust through Transparency, Comp...
 
GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...
GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...
GraphConnect Europe 2016 - Building a Repository of Biomedical Ontologies wit...
 
GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...
GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...
GraphConnect Europe 2016 - How the ICIJ Used Neo4j to Unravel the Panama Pape...
 
GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...
GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...
GraphConnect Europe 2016 - Semantic PIM: Using a Graph Data Model at Toy Manu...
 
Neo4j GraphTalks - Semantische Netze
Neo4j GraphTalks - Semantische NetzeNeo4j GraphTalks - Semantische Netze
Neo4j GraphTalks - Semantische Netze
 
Neo4j GraphTalks - Einführung in Graphdatenbanken
Neo4j GraphTalks - Einführung in GraphdatenbankenNeo4j GraphTalks - Einführung in Graphdatenbanken
Neo4j GraphTalks - Einführung in Graphdatenbanken
 
GraphTalk Berlin - Einführung in Graphdatenbanken
GraphTalk Berlin - Einführung in GraphdatenbankenGraphTalk Berlin - Einführung in Graphdatenbanken
GraphTalk Berlin - Einführung in Graphdatenbanken
 
Introducing Neo4j 3.1: New Security and Clustering Architecture
Introducing Neo4j 3.1: New Security and Clustering Architecture Introducing Neo4j 3.1: New Security and Clustering Architecture
Introducing Neo4j 3.1: New Security and Clustering Architecture
 
GraphTalks Hamburg - Einführung in Graphdatenbanken
GraphTalks Hamburg - Einführung in GraphdatenbankenGraphTalks Hamburg - Einführung in Graphdatenbanken
GraphTalks Hamburg - Einführung in Graphdatenbanken
 

More from Neo4j

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

More from Neo4j (20)

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

Recently uploaded

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 

Recently uploaded (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 

Tips and Tricks for Graph Data Modeling

  • 1. Graph Modeling Tips and Tricks Mark Needham @markhneedham
  • 4. Recommendation queries ‣ Several different types • groups to join • topics to follow • events to attend ‣ As a user of meetup.com trying to find groups to join and events to attend
  • 5. How will this talk be structured?
  • 6. Find similar groups to Neo4j As a member of the Neo4j London group I want to find other similar meetup groups So that I can join those groups
  • 7. What makes groups similar?
  • 8. As a member of the Neo4j London group I want to find other similar meetup groups So that I can join those groups Find similar groups to Neo4j
  • 9. As a member of the Neo4j London group I want to find other similar meetup groups So that I can join those groups Nodes
  • 10. As a member of the Neo4j London group I want to find other similar meetup groups So that I can join those groups Relationships
  • 11. As a member of the Neo4j London group I want to find other similar meetup groups So that I can join those groups Labels
  • 12. As a member of the Neo4j London group I want to find other similar meetup groups So that I can join those groups Properties
  • 13. Find similar groups to Neo4j MATCH (group:Group {name: "Neo4j - London User Group"}) -[:HAS_TOPIC]->(topic)<-[:HAS_TOPIC]-(otherGroup) RETURN otherGroup.name, COUNT(topic) AS topicsInCommon, COLLECT(topic.name) AS topics ORDER BY topicsInCommon DESC, otherGroup.name LIMIT 10
  • 15. Tip: Model incrementally ‣ Build the model for the question we need to answer now then move onto the next question
  • 16. I’m already a member of these!
  • 17. What other data can we get?
  • 18. Exclude groups I’m a member of As a member of the Neo4j London group I want to find other similar meetup groups that I’m not already a member of So that I can join those groups
  • 19. Exclude groups I’m a member of As a member of the Neo4j London group I want to find other similar meetup groups that I’m not already a member of So that I can join those groups
  • 20. Exclude groups I’m a member of MATCH (group:Group {name: "Neo4j - London User Group"}) -[:HAS_TOPIC]->(topic)<-[:HAS_TOPIC]-(otherGroup:Group) RETURN otherGroup.name, COUNT(topic) AS topicsInCommon, EXISTS((:Member {name: "Mark Needham"}) -[:MEMBER_OF]->(otherGroup)) AS alreadyMember, COLLECT(topic.name) AS topics ORDER BY topicsInCommon DESC LIMIT 10
  • 21. Exclude groups I’m a member of
  • 22. Exclude groups I’m a member of MATCH (group:Group {name: "Neo4j - London User Group"}) -[:HAS_TOPIC]->(topic)<-[:HAS_TOPIC]-(otherGroup:Group) WHERE NOT( (:Member {name: "Mark Needham"}) -[:MEMBER_OF]->(otherGroup) ) RETURN otherGroup.name, COUNT(topic) AS topicsInCommon, COLLECT(topic.name) AS topics ORDER BY topicsInCommon DESC LIMIT 10
  • 23. Exclude groups I’m a member of
  • 24. Find my similar groups As a member of several meetup groups I want to find other similar meetup groups that I’m not already a member of So that I can join those groups
  • 25. Find my similar groups As a member of several meetup groups I want to find other similar meetup groups that I’m not already a member of So that I can join those groups
  • 26. Find my similar groups MATCH (member:Member {name: "Mark Needham"}) -[:INTERESTED_IN]->(topic), (member)-[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic) WITH member, topic, COUNT(*) AS score MATCH (topic)<-[:HAS_TOPIC]-(otherGroup) WHERE NOT (member)-[:MEMBER_OF]->(otherGroup) RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score ORDER BY score DESC
  • 27. Find my similar groups
  • 29. Oops...Jonny has no interests!
  • 30. What is Jonny interested in? As a member of several meetup groups I want to find other similar meetup groups that I’m not already a member of So that I can join those groups INTERESTED_IN?
  • 31. What is Jonny interested in? There’s an implicit INTERESTED_IN relationship between the topics of groups I belong to but don’t express an interest in. Let’s make it explicit P G T MEMBER_OF HAS_TOPIC P G T MEMBER_OF HAS_TOPIC INTERESTED_IN
  • 32. What is Jonny interested in? MATCH (m:Member)-[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic) WITH m, topic, COUNT(*) AS times WHERE times > 3 MERGE (m)-[:INTERESTED_IN]->(topic)
  • 33. What is Jonny interested in?
  • 34. Tip: Make the implicit explicit ‣ Fill in the missing links in the graph ‣ You could run this type of query once a day during a quiet period ‣ On bigger graphs we’d run it in batches to avoid loading the whole database into memory
  • 35. Find next group people join As a member of a meetup group I want to find out which meetup groups other people join after this one So that I can join those groups
  • 36. Find next group people join MATCH (group:Group {name: "Neo4j - London User Group"}) <-[membership:MEMBER_OF]-(member), (member)-[otherMembership:MEMBER_OF]->(otherGroup) WHERE membership.joined < otherMembership.joined WITH member, otherGroup ORDER BY otherMembership.joined WITH member, COLLECT(otherGroup)[0] AS nextGroup RETURN nextGroup.name, COUNT(*) AS times ORDER BY times DESC
  • 37. Find next group people join
  • 38. It feels a bit clunky... MATCH (group:Group {name: "Neo4j - London User Group"}) <-[membership:MEMBER_OF]-(member), (member)-[otherMembership:MEMBER_OF]->(otherGroup) WHERE membership.joined < otherMembership.joined WITH member, otherGroup ORDER BY otherMembership.joined WITH member, COLLECT(otherGroup)[0] AS nextGroup RETURN nextGroup.name, COUNT(*) AS times ORDER BY times DESC ‣ We have to scan through all the MEMBER_OF relationships to find the one we want ‣ It might make our lives easier if we made membership a first class citizen of the domain
  • 41. Refactor to facts MATCH (member:Member)-[rel:MEMBER_OF]->(group) MERGE (membership:Membership {id: member.id + "_" + group.id}) SET membership.joined = rel.joined MERGE (member)-[:HAS_MEMBERSHIP]->(membership) MERGE (membership)-[:OF_GROUP]->(group)
  • 42. Refactor to facts MATCH (member:Member)-[:HAS_MEMBERSHIP]->(membership) WITH member, membership ORDER BY member.id, membership.joined WITH member, COLLECT(membership) AS memberships UNWIND RANGE(0,SIZE(memberships) - 2) as idx WITH memberships[idx] AS m1, memberships[idx+1] AS m2 MERGE (m1)-[:NEXT]->(m2)
  • 43. Find next group people join MATCH (group:Group {name: "Neo4j - London User Group"}) <-[:OF_GROUP]-(membership)-[:NEXT]->(nextMembership), (membership)<-[:HAS_MEMBERSHIP]-(member:Member) -[:HAS_MEMBERSHIP]->(nextMembership), (nextMembership)-[:OF_GROUP]->(nextGroup) RETURN nextGroup.name, COUNT(*) AS times ORDER BY times DESC
  • 44. Comparing the approaches vs MATCH (group:Group {name: "Neo4j - London User Group"}) <-[membership:MEMBER_OF]-(member), (member)-[otherMembership:MEMBER_OF]->(otherGroup) WITH member, membership, otherMembership, otherGroup ORDER BY member.id, otherMembership.joined WHERE membership.joined < otherMembership.joined WITH member, membership, COLLECT(otherGroup)[0] AS nextGroup RETURN nextGroup.name, COUNT(*) AS times ORDER BY times DESC MATCH (group:Group {name: "Neo4j - London User Group"}) <-[:OF_GROUP]-(membership)-[:NEXT]->(nextMembership), (membership)<-[:HAS_MEMBERSHIP]-(member:Member) -[:HAS_MEMBERSHIP]->(nextMembership), (nextMembership)-[:OF_GROUP]->(nextGroup) RETURN nextGroup.name, COUNT(*) AS times ORDER BY times DESC
  • 45. How do I profile a query? ‣ EXPLAIN • shows the execution plan without actually executing it or returning any results. ‣ PROFILE • executes the statement and returns the results along with profiling information. 45
  • 46. Neo4j’s longest plan (so far…) 46
  • 47. Neo4j’s longest plan (so far…) 47
  • 48. Neo4j’s longest plan (so far…) 48
  • 49. What is our goal? At a high level, the goal is simple: get the number of db hits down. 49
  • 50. an abstract unit of storage engine work. What is a database hit? “ ” 50
  • 51. Comparing the approaches Cypher version: CYPHER 2.3, planner: COST. 111656 total db hits in 330 ms. vs Cypher version: CYPHER 2.3, planner: COST. 23650 total db hits in 60 ms.
  • 52. Tip: Profile your queries ‣ Spike the different models and see which one performs the best
  • 53. Should we keep both models? We could but when we add, edit or remove a membership we’d have to keep both graph structures in sync.
  • 54. Adding a group membership WITH "Mark Needham" AS memberName, "Neo4j - London User Group" AS groupName, timestamp() AS now MATCH (group:Group {name: groupName}) MATCH (member:Member {name: memberName}) MERGE (member)-[memberOfRel:MEMBER_OF]->(group) ON CREATE SET memberOfRel.time = now MERGE (membership:Membership {id: member.id + "_" + group.id}) ON CREATE SET membership.joined = now MERGE (member)-[:HAS_MEMBERSHIP]->(membership) MERGE (membership)-[:OF_GROUP]->(group)
  • 55. Removing a group membership WITH "Mark Needham" AS memberName, "Neo4j - London User Group" AS groupName, timestamp() AS now MATCH (group:Group {name: groupName}) MATCH (member:Member {name: memberName}) MATCH (member)-[memberOfRel:MEMBER_OF]->(group) MATCH (membership:Membership {id: member.id + "_" + group.id}) MATCH (member)-[hasMembershipRel:HAS_MEMBERSHIP]->(membership) MATCH (membership)-[ofGroupRel:OF_GROUP]->(group) DELETE memberOfRel, hasMembershipRel, ofGroupRel, membership
  • 57. ...not so fast! As a member of several meetup groups I want to find other similar meetup groups that I’m not already a member of So that I can join those groups
  • 58. Why not delete MEMBER_OF? MATCH (member:Member {name: "Mark Needham"}) -[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic) WITH member, topic, COUNT(*) AS score MATCH (topic)<-[:HAS_TOPIC]-(otherGroup) WHERE NOT (member)-[:MEMBER_OF]->(otherGroup) RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score ORDER BY score DESC MATCH (member:Member {name: "Mark Needham"}) -[:HAS_MEMBERSHIP]->()-[:OF_GROUP]->(group:Group)-[:HAS_TOPIC]->(topic) WITH member, topic, COUNT(*) AS score MATCH (topic)<-[:HAS_TOPIC]-(otherGroup) WHERE NOT (member)-[:HAS_MEMBERSHIP]->(:Membership)-[:OF_GROUP]->(otherGroup:Group) RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score ORDER BY score DESC
  • 59. Why not delete MEMBER_OF? MATCH (member:Member {name: "Mark Needham"}) -[:MEMBER_OF]->(group)-[:HAS_TOPIC]->(topic) WITH member, topic, COUNT(*) AS score MATCH (topic)<-[:HAS_TOPIC]-(otherGroup) WHERE NOT (member)-[:MEMBER_OF]->(otherGroup) RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score ORDER BY score DESC MATCH (member:Member {name: "Mark Needham"}) -[:HAS_MEMBERSHIP]->()-[:OF_GROUP]->(group:Group)-[:HAS_TOPIC]->(topic) WITH member, topic, COUNT(*) AS score MATCH (topic)<-[:HAS_TOPIC]-(otherGroup) WHERE NOT (member)-[:HAS_MEMBERSHIP]->(:Membership)-[:OF_GROUP]->(otherGroup:Group) RETURN otherGroup.name, COLLECT(topic.name), SUM(score) as score ORDER BY score DESC 433318 total db hits in 485 ms. 83268 total db hits in 117 ms.
  • 60. Tip: Maintaining multiple models ‣ Different models perform better for different queries but worse for others ‣ Optimising for reads may mean we pay a write and maintenance penalty
  • 62. Events in my groups As a member of several meetup groups who has previously attended events I want to find other events hosted by those groups So that I can attend those events
  • 63. Events in my groups As a member of several meetup groups who has previously attended events I want to find other events hosted by those groups So that I can attend those events
  • 64. WITH 24.0*60*60*1000 AS oneDay MATCH (member:Member {name: "Mark Needham"}), (member)-[:MEMBER_OF]->(group), (group)-[:HOSTED_EVENT]->(futureEvent) WHERE futureEvent.time >= timestamp() AND NOT (member)-[:RSVPD]->(futureEvent) RETURN group.name, futureEvent.name, round((futureEvent.time - timestamp()) / oneDay) AS days ORDER BY days LIMIT 10 Events in my groups
  • 65. Events in my groups
  • 66. + previous events attended WITH 24.0*60*60*1000 AS oneDay MATCH (member:Member {name: "Mark Needham"}) MATCH (futureEvent:Event) WHERE futureEvent.time >= timestamp() AND NOT (member)-[:RSVPD]->(futureEvent) MATCH (futureEvent)<-[:HOSTED_EVENT]-(group) WITH oneDay, group, futureEvent, member, EXISTS((group)<-[:MEMBER_OF]-(member)) AS isMember OPTIONAL MATCH (member)-[rsvp:RSVPD {response: "yes"}]->(pastEvent)<-[:HOSTED_EVENT]-(group) WHERE pastEvent.time < timestamp() RETURN group.name, futureEvent.name, isMember, COUNT(rsvp) AS previousEvents, round((futureEvent.time - timestamp()) / oneDay) AS days ORDER BY days, previousEvents DESC
  • 67. + previous events attended
  • 68. RSVPD_YES vs RSVPD I was curious whether refactoring RSVPD {response: "yes"} to RSVPD_YES would have any impact as Neo4j is optimised for querying by unique relationship types.
  • 69. Refactor to specific relationships MATCH (m:Member)-[rsvp:RSVPD {response:"yes"}]->(event) MERGE (m)-[rsvpYes:RSVPD_YES {id: rsvp.id}]->(event) ON CREATE SET rsvpYes.created = rsvp.created, rsvpYes.lastModified = rsvp.lastModified; MATCH (m:Member)-[rsvp:RSVPD {response:"no"}]->(event) MERGE (m)-[rsvpYes:RSVPD_NO {id: rsvp.id}]->(event) ON CREATE SET rsvpYes.created = rsvp.created, rsvpYes.lastModified = rsvp.lastModified;
  • 70. RSVPD_YES vs RSVPD RSVPD {response: "yes"} vs RSVPD_YES Cypher version: CYPHER 2.3, planner: COST. 688635 total db hits in 232 ms. Cypher version: CYPHER 2.3, planner: COST. 559866 total db hits in 207 ms.
  • 71. Why would we keep RSVPD? MATCH (m:Member)-[r:RSVPD]->(event)<-[:HOSTED_EVENT]-(group) WHERE m.name = "Mark Needham" RETURN event, group, r MATCH (m:Member)-[r:RSVPD_YES|:RSVPD_NO|:RSVPD_WAITLIST]->(event), (event)<-[:HOSTED_EVENT]-(group) WHERE m.name = "Mark Needham" RETURN event, group, r
  • 72. Tip: Specific relationships ‣ Neo4j is optimised for querying by unique relationship types… ‣ ...but sometimes we pay a query maintenance cost to achieve this
  • 73. + events my friends are attending There’s an implicit FRIENDS relationship between people who attended the same events. Let’s make it explicit. M E M RSVPD RSVPD FRIENDS M E M RSVPD RSVPD
  • 74. + events my friends are attending MATCH (m1:Member) WHERE NOT m1:Processed WITH m1 LIMIT {limit} MATCH (m1)-[:RSVP_YES]->(event:Event)<-[:RSVP_YES]-(m2:Member) WITH m1, m2, COLLECT(event) AS events, COUNT(*) AS times WHERE times >= 5 WITH m1, m2, times, [event IN events | SIZE((event)<-[:RSVP_YES]-())] AS attendances WITH m1, m2, REDUCE(score = 0.0, a IN attendances | score + (1.0 / a)) AS score MERGE (m1)-[friendsRel:FRIENDS]-(m2) SET friendsRel.score = row.score
  • 75. Bidirectional relationships ‣ You may have noticed that we didn’t specify a direction when creating the relationship MERGE (m1)-[:FRIENDS]-(m2) ‣ FRIENDS is a bidirectional relationship. We only need to create it once between two people. ‣ We ignore the direction when querying
  • 76. + events my friends are attending WITH 24.0*60*60*1000 AS oneDay MATCH (member:Member {name: "Mark Needham"}) MATCH (futureEvent:Event) WHERE futureEvent.time >= timestamp() AND NOT (member)-[:RSVPD]->(futureEvent) MATCH (futureEvent)<-[:HOSTED_EVENT]-(group) WITH oneDay, group, futureEvent, member, EXISTS((group)<-[:MEMBER_OF]-(member)) AS isMember OPTIONAL MATCH (member)-[rsvp:RSVPD {response: "yes"}]->(pastEvent)<-[:HOSTED_EVENT]-(group) WHERE pastEvent.time < timestamp() WITH oneDay, group, futureEvent, member, isMember, COUNT(rsvp) AS previousEvents OPTIONAL MATCH (futureEvent)<-[:HOSTED_EVENT]-()-[:HAS_TOPIC]->(topic)<-[:INTERESTED_IN]-(member) WITH oneDay, group, futureEvent, member, isMember, previousEvents, COUNT(topic) AS topics OPTIONAL MATCH (member)-[:FRIENDS]-(:Member)-[rsvpYes:RSVP_YES]->(futureEvent) RETURN group.name, futureEvent.name, isMember, round((futureEvent.time - timestamp()) / oneDay) AS days, previousEvents, topics, COUNT(rsvpYes) AS friendsGoing ORDER BY days, friendsGoing DESC, previousEvents DESC LIMIT 15
  • 77. + events my friends are attending
  • 78. Tip: Bidirectional relationships ‣ Some relationships are bidirectional in nature ‣ Neo4j always stores relationships with a direction but we can choose to ignore that when we query
  • 79. tl;dr ‣ Model incrementally ‣ Always profile your queries ‣ Consider making the implicit explicit… • ...but beware the maintenance cost ‣ Be specific with relationship types ‣ Ignore direction for bidirectional relationships
  • 80. That’s all for today! Questions? :-) Mark Needham @markhneedham https://github.com/neo4j-meetups/modeling-worked-example