You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2024/08/20 02:42:37 UTC

(groovy-website) branch asf-site updated: preliminary version of graphdb post

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-website.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 7e2fda2  preliminary version of graphdb post
7e2fda2 is described below

commit 7e2fda2e95eef0f5e617e6dda76f7f1e77beac1a
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Aug 20 12:42:26 2024 +1000

    preliminary version of graphdb post
---
 site/src/site/blog/groovy-graph-databases.adoc | 147 +++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

diff --git a/site/src/site/blog/groovy-graph-databases.adoc b/site/src/site/blog/groovy-graph-databases.adoc
new file mode 100644
index 0000000..94f43b2
--- /dev/null
+++ b/site/src/site/blog/groovy-graph-databases.adoc
@@ -0,0 +1,147 @@
+= Using Graph Databases with Groovy
+Paul King
+:revdate: 2024-08-20T10:18:00+00:00
+:keywords: tugraph, neo4j, apache age, graph databases, groovy
+:draft: true
+:description: This post illustrates using graph databases with Groovy.
+
+The Olympics is over for another 4 years. For sports fans, there were many exciting moments.
+Let's look at just one event where the Olympic record was broken several times over the
+last three years. We'll look at the women's 100m backstroke and model the results as a graph database.
+
+We'll have vertices in our graph database corresponding to the swimmers and the swims.
+We'll use the labels `swimmer` and `swim` for these vertices. We'll have relationships
+such as `swam` and `supercedes` between vertices. We'll explore modelling and querying the event
+information using several graph database technologies.
+
+== Apache TinkerPop
+
+Our first technology to examine is https://tinkerpop.apache.org/[Apache TinkerPopβ„’].
+
+image:https://tinkerpop.apache.org/img/tinkerpop-splash.png[tinkerpop logo]
+
+TinkerPop is an open source computing framework for graph databases. It provides
+a common abstraction layer, and a graph query language, called Gremlin.
+This allows you to work with numerous graph database implementations in a consistent way.
+TinkerPop also provides its own graph engine implementation, called TinkerGraph, which is what
+we'll use initially.
+
+We'll look at the swims in the 2021 and 2024 Olympic finals as well as any preliminary swims
+where the Olympic record was broken.
+
+Let's first create the information relevant for the previous Olympic record which was set
+at the London 2012 Olympics. Emily Seebohm set that record in Heat 4:
+
+[source,groovy]
+----
+var graph = TinkerGraph.open()
+var g = traversal().withEmbedded(graph)
+var es = g.addV('swimmer').property(name: 'Emily Seebohm', country: 'πŸ‡¦πŸ‡Ί').next()
+swim1 = g.addV('swim').property(where: 'London 2012', event: 'Heat 4', time: 58.23, result: 'First').next()
+es.addEdge('swam', swim1)
+----
+
+[source,groovy]
+----
+var (name, country) = ['name', 'country'].collect { g.V(es).values(it)[0] }
+var (where, event, time) = ['where', 'event', 'time'].collect { g.V(swim1).values(it)[0] }
+println "$name from $country swam a time of $time in $event at the $where Olympics"
+----
+
+And here is the output:
+
+----
+Emily Seebohm from πŸ‡¦πŸ‡Ί swam a time of 58.23 in Heat 4 at the London 2012 Olympics
+----
+
+Let's create some helper methods to simplify creation of the remaining information.
+
+[source,groovy]
+----
+def insertSwimmer(TraversalSource g, name, country) {
+    g.addV('swimmer').property(name: name, country: country).next()
+}
+
+def insertSwim(TraversalSource g, where, event, time, result, swimmer) {
+    var swim = g.addV('swim').property(where: where, event: event, time: time, result: result).next()
+    swimmer.addEdge('swam', swim)
+    swim
+}
+----
+
+Now we can create the remaining swim information:
+
+[source,groovy]
+----
+var km = insertSwimmer(g, 'Kylie Masse', 'πŸ‡¨πŸ‡¦')
+var swim2 = insertSwim(g, 'Tokyo 2021', 'Heat 4', 58.17, 'First', km)
+swim2.addEdge('supercedes', swim1)
+var swim3 = insertSwim(g, 'Tokyo 2021', 'Final', 57.72, 'πŸ₯ˆ', km)
+
+var rs = insertSwimmer(g, 'Regan Smith', 'πŸ‡ΊπŸ‡Έ')
+var swim4 = insertSwim(g, 'Tokyo 2021', 'Heat 5', 57.96, 'First', rs)
+swim4.addEdge('supercedes', swim2)
+var swim5 = insertSwim(g, 'Tokyo 2021', 'Semifinal 1', 57.86, '', rs)
+var swim6 = insertSwim(g, 'Tokyo 2021', 'Final', 58.05, 'πŸ₯‰', rs)
+var swim7 = insertSwim(g, 'Paris 2024', 'Final', 57.66, 'πŸ₯ˆ', rs)
+var swim8 = insertSwim(g, 'Paris 2024', 'Relay leg1', 57.28, 'First', rs)
+
+var kmk = insertSwimmer(g, 'Kaylie McKeown', 'πŸ‡¦πŸ‡Ί')
+var swim9 = insertSwim(g, 'Tokyo 2021', 'Heat 6', 57.88, 'First', kmk)
+swim9.addEdge('supercedes', swim4)
+swim5.addEdge('supercedes', swim9)
+var swim10 = insertSwim(g, 'Tokyo 2021', 'Final', 57.47, 'πŸ₯‡', kmk)
+swim10.addEdge('supercedes', swim5)
+var swim11 = insertSwim(g, 'Paris 2024', 'Final', 57.33, 'πŸ₯‡', kmk)
+swim11.addEdge('supercedes', swim10)
+swim8.addEdge('supercedes', swim11)
+
+var kb = insertSwimmer(g, 'Katharine Berkoff', 'πŸ‡ΊπŸ‡Έ')
+var swim12 = insertSwim(g, 'Paris 2024', 'Final', 57.98, 'πŸ₯‰', kb)
+----
+
+[source,groovy]
+----
+var successInParis = g.V().out('swam').has('where', 'Paris 2024').in()
+    .values('country').toSet()
+assert successInParis == ['πŸ‡ΊπŸ‡Έ', 'πŸ‡¦πŸ‡Ί'] as Set
+----
+
+[source,groovy]
+----
+var recordSetInHeat = g.V().hasLabel('swim')
+    .filter { it.get().property('event').value().startsWith('Heat') }
+    .values('where').toSet()
+assert recordSetInHeat == ['London 2012', 'Tokyo 2021'] as Set
+----
+
+[source,groovy]
+----
+var recordTimesInFinals = g.V().has('event', 'Final').as('ev').out('supercedes')
+    .select('ev').values('time').toSet()
+assert recordTimesInFinals == [57.47, 57.33] as Set
+----
+
+[source,groovy]
+----
+println "Olympic records after ${g.V(swim1).values('where', 'event').toList().join(' ')}: "
+println g.V(swim1).repeat(in('supercedes') ).as('sw').emit()
+    .values('where').concat(' ')
+    .concat(select('sw').values('event')).toList().join('\n')
+----
+
+Which has this output:
+
+[source,groovy]
+----
+Olympic records after London 2012 Heat 4:
+Tokyo 2021 Heat 4
+Tokyo 2021 Heat 5
+Tokyo 2021 Heat 6
+Tokyo 2021 Semifinal 1
+Tokyo 2021 Final
+Paris 2024 Final
+Paris 2024 Relay leg1
+----
+
+