Bestandteile
Übersicht
Bekannte Knowledge Graphs
GQL – Graph Query Language (ISO 2024)
SQL/PGQ (ISO 2023)
GRAPH_TABLE)GQL Beispiel
-- GQL: Freunde zweiten Grades
MATCH (a:Person WHERE a.name = 'Alice')
-[:KENNT]->(b:Person)
-[:KENNT]->(c:Person)
WHERE NOT EXISTS {
MATCH (a)-[:KENNT]->(c)
}
RETURN c.name AS Empfehlung
SQL/PGQ Beispiel
-- SQL/PGQ: Freunde von Alice
SELECT person_b.name
FROM GRAPH_TABLE (social_graph
MATCH (a IS Person)
-[IS KENNT]->(b IS Person)
WHERE a.name = 'Alice'
COLUMNS (b.name AS name)
) AS person_b
(n) = Knoten, -[r]-> = gerichtete Kante// Knoten anlegen
CREATE (a:Person {name: "Alice", age: 32})
CREATE (b:Person {name: "Bob"})
// Beziehung anlegen
MATCH (a:Person {name: "Alice"}),
(b:Person {name: "Bob"})
CREATE (a)-[:KENNT {seit: 2018}]->(b)
// Abfrage: alle Freunde von Alice
MATCH (a:Person {name: "Alice"})
-[:KENNT]->(friend)
RETURN friend.name
?s ?p ?o-- foaf - friend of a friend
PREFIX ex: <http://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
-- Alle Personen aus Berlin
SELECT ?name ?age
WHERE {
?person a foaf:Person ;
foaf:name ?name ;
foaf:age ?age ;
ex:wohntIn ex:Berlin .
FILTER (?age > 25)
}
ORDER BY ?name
-- Wikidata: Hauptstädte aller Länder
SELECT ?land ?hauptstadt WHERE {
?l wdt:P31 wd:Q6256 ;
wdt:P36 ?hs .
}
-- Alle Nobelpreisträger aus Deutschland
SELECT ?person ?name WHERE {
?person wdt:P27 wd:Q183 ; # Deutsch
wdt:P166 ?prize . # Auszeichnung
?prize wdt:P31 wd:Q7191 . # Nobelpreis
?person rdfs:label ?name .
FILTER (lang(?name) = "de")
}
g.V(): alle Knoteng.E(): alle Kanten// Alle Freunde von Alice
g.V().has("name", "Alice")
.out("KENNT")
.values("name")
// Freunde zweiten Grades
g.V().has("name", "Alice")
.out("KENNT").out("KENNT")
.dedup()
.values("name")
// Kuerzester Pfad
g.V().has("name","Alice")
.repeat(out().simplePath())
.until(has("name","Charlie"))
.path().limit(1)
Apache TinkerPop
JanusGraph
GSQL Beispiel
// Freunde zweiten Grades
CREATE QUERY fof(VERTEX src)
FOR GRAPH SocialGraph {
SetAccum @@friends, @@fof;
start = {src};
hop1 = SELECT t FROM start:s
-(KENNT:e)-> Person:t
ACCUM @@friends += t;
hop2 = SELECT t FROM hop1:s
-(KENNT:e)-> Person:t
WHERE t NOT IN @@friends
AND t != src
ACCUM @@fof += t;
PRINT @@fof;
}
CREATE PROPERTY GRAPH: deklariert Knoten- und KantentabellenGRAPH_TABLE eingebettet in SQLOracle Graph Server (PGX)
-- Property Graph definieren (Oracle 23c)
CREATE PROPERTY GRAPH social_graph
VERTEX TABLES (
person
KEY (id)
LABEL Person
PROPERTIES (name, age)
)
EDGE TABLES (
freundschaft
KEY (id)
SOURCE KEY (person_id)
REFERENCES person
DESTINATION KEY (freund_id)
REFERENCES person
LABEL KENNT
PROPERTIES (seit)
);
-- Graphmuster in SQL abfragen
SELECT f.name AS freund
FROM GRAPH_TABLE (social_graph
MATCH (p IS Person)
-[IS KENNT]->(f IS Person)
WHERE p.name = 'Alice'
COLUMNS (f.name)
)
ORDER BY freund;
// Verbindung (Python, Gremlin-Client)
from gremlin_python.driver import client
c = client.Client(
'wss://myaccount.gremlin.cosmos.azure.com:443/',
graph='g',
username='...',
password='...')
// Knoten und Kante anlegen
c.submit(
"g.addV('Person')"
" .property('id','alice')"
" .property('name','Alice')"
" .property('pk','pk')")
c.submit(
"g.V('alice').addE('KENNT')"
" .to(g.V('bob'))"
" .property('seit', 2018)")
// Freunde von Alice
c.submit(
"g.V('alice').out('KENNT')"
" .values('name')")
CREATE PROPERTY GRAPH definiert Knoten- und KantentabellenFROM GRAPH_TABLE(...) eingebettet in normales SQLCREATE TABLE Person AS
SELECT * FROM 'https://.../person.csv';
CREATE TABLE Person_knows_person AS
SELECT * FROM 'https://.../person_knows_person.csv';
CREATE PROPERTY GRAPH snb
VERTEX TABLES (
Person
)
EDGE TABLES (
Person_knows_person
SOURCE KEY ( person1id ) REFERENCES Person ( id )
DESTINATION KEY ( person2id ) REFERENCES Person ( id )
LABEL Knows
);
FROM GRAPH_TABLE(snb
MATCH (a:Person WHERE a.firstName = 'Jan')-[k:Knows]->(b:Person)
COLUMNS (b.firstName)
);
Gleiche Abfrage im Vergleich
-- SQL: Freunde zweiten Grades
SELECT DISTINCT f2.name
FROM person p
JOIN friendship f1
ON p.id = f1.person_id
JOIN person p1
ON f1.friend_id = p1.id
JOIN friendship f2
ON p1.id = f2.person_id
JOIN person p2
ON f2.friend_id = p2.id
WHERE p.name = 'Alice'
AND p2.id != p.id
AND p2.id NOT IN (
SELECT friend_id
FROM friendship
WHERE person_id = p.id)
// Cypher: Freunde zweiten Grades
MATCH (a:Person {name: "Alice"})
-[:KENNT*2]->(fof)
WHERE NOT (a)-[:KENNT]->(fof)
AND fof <> a
RETURN DISTINCT fof.name
Wann Graphdatenbank?