03_Projects_Query
PDF-Dokumente
| Dateiname | Aktion |
|---|---|
| PDFUebung_Taxi.pdf | Öffnen |
Lernmaterialien
Alles löschen
MATCH (n) DETACH DELETE n;
Projekt 01 – Bibliothek
1) Titel
Bibliothek: Member – Book
2) Kurzbeschreibung
Mitglieder suchen nach Büchern und leihen Bücher aus. So kann man Such- und Ausleihverhalten vergleichen.
3) Nodes & Relations
Nodes:
:Member(memberId, name, email),:Book(bookId, title, genre, year)Relations:
(:Member)-[:SEARCHED_FOR {at, query}]->(:Book)(:Member)-[:BORROWED {at, dueDate}]->(:Book)
4) Befüllen (Cypher)
CREATE CONSTRAINT p01_member_id_unique IF NOT EXISTS
FOR (m:Member) REQUIRE m.memberId IS UNIQUE;
CREATE CONSTRAINT p01_book_id_unique IF NOT EXISTS
FOR (b:Book) REQUIRE b.bookId IS UNIQUE;
MERGE (m1:Member {memberId:"M001"}) SET m1.name="Anna", m1.email="anna@example.com";
MERGE (m2:Member {memberId:"M002"}) SET m2.name="Ben", m2.email="ben@example.com";
MERGE (b1:Book {bookId:"B100"}) SET b1.title="1984", b1.genre="Fiction", b1.year=1949;
MERGE (b2:Book {bookId:"B200"}) SET b2.title="Dune", b2.genre="SciFi", b2.year=1965;
MERGE (b3:Book {bookId:"B300"}) SET b3.title="Sapiens", b3.genre="Nonfiction", b3.year=2011;
MATCH (m1:Member {memberId:"M001"}), (b2:Book {bookId:"B200"})
MERGE (m1)-[:SEARCHED_FOR {at: datetime("2026-01-10T10:15:00"), query:"best scifi"}]->(b2);
MATCH (m1:Member {memberId:"M001"}), (b2:Book {bookId:"B200"})
MERGE (m1)-[:BORROWED {at: datetime("2026-01-10T10:45:00"), dueDate: date("2026-01-24")}]->(b2);
MATCH (m2:Member {memberId:"M002"}), (b3:Book {bookId:"B300"})
MERGE (m2)-[:SEARCHED_FOR {at: datetime("2026-01-11T09:05:00"), query:"history bestseller"}]->(b3);
5) Abfragen (ohne Lösung)
Liste alle Mitglieder, die mindestens ein Buch ausgeliehen haben.
Zeige die Top-Bücher nach Anzahl SEARCHED_FOR.
Zeige Bücher, die gesucht aber nie ausgeliehen wurden.
Zeige Mitglieder, die alle Bücher ausgeliehen haben.
“Market Basket”: Mitglieder, die Buch X ausgeliehen haben, liehen auch welches Buch?
Projekt 02 – Streaming
1) Titel
Streaming: User – Movie
2) Kurzbeschreibung
Nutzer suchen Filme und schauen sie. Beziehungen speichern Suchanfrage, Fortschritt und Bewertung.
3) Nodes & Relations
Nodes:
:User(userId, name, email),:Movie(movieId, title, genre, year)Relations:
(:User)-[:SEARCHED_FOR {at, query}]->(:Movie)(:User)-[:WATCHED {at, progressPct, rating}]->(:Movie)
4) Befüllen (Cypher)
CREATE CONSTRAINT p02_user_id_unique IF NOT EXISTS
FOR (u:User) REQUIRE u.userId IS UNIQUE;
CREATE CONSTRAINT p02_movie_id_unique IF NOT EXISTS
FOR (m:Movie) REQUIRE m.movieId IS UNIQUE;
MERGE (u1:User {userId:"U001"}) SET u1.name="Clara", u1.email="clara@example.com";
MERGE (u2:User {userId:"U002"}) SET u2.name="David", u2.email="david@example.com";
MERGE (m1:Movie {movieId:"MV100"}) SET m1.title="Inception", m1.genre="SciFi", m1.year=2010;
MERGE (m2:Movie {movieId:"MV200"}) SET m2.title="Interstellar", m2.genre="SciFi", m2.year=2014;
MERGE (m3:Movie {movieId:"MV300"}) SET m3.title="La La Land", m3.genre="Drama", m3.year=2016;
MATCH (u1:User {userId:"U001"}), (m2:Movie {movieId:"MV200"})
MERGE (u1)-[:SEARCHED_FOR {at: datetime("2026-01-12T18:15:00"), query:"space movie"}]->(m2);
MATCH (u1:User {userId:"U001"}), (m2:Movie {movieId:"MV200"})
MERGE (u1)-[:WATCHED {at: datetime("2026-01-12T20:00:00"), progressPct: 100, rating: 5}]->(m2);
MATCH (u2:User {userId:"U002"}), (m3:Movie {movieId:"MV300"})
MERGE (u2)-[:SEARCHED_FOR {at: datetime("2026-01-13T21:05:00"), query:"musical romance"}]->(m3);
5) Abfragen (ohne Lösung)
Top-User nach Anzahl WATCHED.
Filme, die gesucht aber nicht geschaut wurden.
Durchschnittliche Bewertung pro Film.
User, die alle Filme geschaut haben.
Empfehlungen: “Wer Film A geschaut hat, schaute auch …”.
Projekt 03 – Flugportal
1) Titel
Reisen: Traveler – Flight
2) Kurzbeschreibung
Reisende suchen Flüge und buchen einen Flug. Buchungsdaten (Preis, Sitzplatz) liegen auf der Beziehung.
3) Nodes & Relations
Nodes:
:Traveler(travelerId, name, email),:Flight(flightId, route, departure, airline)Relations:
(:Traveler)-[:SEARCHED_FOR {at, query}]->(:Flight)(:Traveler)-[:BOOKED {at, bookingId, seat, price, currency}]->(:Flight)
4) Befüllen (Cypher)
CREATE CONSTRAINT p03_traveler_id_unique IF NOT EXISTS
FOR (t:Traveler) REQUIRE t.travelerId IS UNIQUE;
CREATE CONSTRAINT p03_flight_id_unique IF NOT EXISTS
FOR (f:Flight) REQUIRE f.flightId IS UNIQUE;
MERGE (t1:Traveler {travelerId:"T001"}) SET t1.name="Eva", t1.email="eva@example.com";
MERGE (t2:Traveler {travelerId:"T002"}) SET t2.name="Felix", t2.email="felix@example.com";
MERGE (f1:Flight {flightId:"F100"}) SET f1.route="VIE→CDG", f1.departure=date("2026-02-01"), f1.airline="AirX";
MERGE (f2:Flight {flightId:"F200"}) SET f2.route="VIE→LHR", f2.departure=date("2026-02-05"), f2.airline="SkyJet";
MERGE (f3:Flight {flightId:"F300"}) SET f3.route="VIE→FRA", f3.departure=date("2026-02-10"), f3.airline="EuroFly";
MATCH (t1:Traveler {travelerId:"T001"}), (f2:Flight {flightId:"F200"})
MERGE (t1)-[:SEARCHED_FOR {at: datetime("2026-01-14T08:10:00"), query:"cheap london flight"}]->(f2);
MATCH (t1:Traveler {travelerId:"T001"}), (f2:Flight {flightId:"F200"})
MERGE (t1)-[:BOOKED {at: datetime("2026-01-14T08:20:00"), bookingId:"BKG-9001", seat:"12A", price:129.0, currency:"EUR"}]->(f2);
MATCH (t2:Traveler {travelerId:"T002"}), (f1:Flight {flightId:"F100"})
MERGE (t2)-[:SEARCHED_FOR {at: datetime("2026-01-14T09:05:00"), query:"paris weekend"}]->(f1);
5) Abfragen (ohne Lösung)
Reisende, die mindestens einen Flug gebucht haben.
Top-Routen nach Anzahl Buchungen.
Flüge gesucht aber nicht gebucht.
Reisende, die alle Flüge gebucht haben.
Durchschnittspreis pro Airline (aus BOOKED-Properties).
Projekt 04 – Jobportal
1) Titel
Jobs: Candidate – JobPosting
2) Kurzbeschreibung
Kandidaten suchen Stellenanzeigen und bewerben sich. Bewerbungseigenschaften werden als Relationship-Properties gespeichert.
3) Nodes & Relations
Nodes:
:Candidate(candidateId, name, email),:JobPosting(jobId, title, city, level)Relations:
(:Candidate)-[:SEARCHED_FOR {at, query}]->(:JobPosting)(:Candidate)-[:APPLIED_TO {at, applicationId, cvVersion}]->(:JobPosting)
4) Befüllen (Cypher)
CREATE CONSTRAINT p04_candidate_id_unique IF NOT EXISTS
FOR (c:Candidate) REQUIRE c.candidateId IS UNIQUE;
CREATE CONSTRAINT p04_job_id_unique IF NOT EXISTS
FOR (j:JobPosting) REQUIRE j.jobId IS UNIQUE;
MERGE (c1:Candidate {candidateId:"CAND1"}) SET c1.name="Gina", c1.email="gina@example.com";
MERGE (c2:Candidate {candidateId:"CAND2"}) SET c2.name="Hannes", c2.email="hannes@example.com";
MERGE (j1:JobPosting {jobId:"J100"}) SET j1.title="Junior DBA", j1.city="Vienna", j1.level="Junior";
MERGE (j2:JobPosting {jobId:"J200"}) SET j2.title="Backend Dev", j2.city="Graz", j2.level="Mid";
MERGE (j3:JobPosting {jobId:"J300"}) SET j3.title="Data Analyst", j3.city="Linz", j3.level="Junior";
MATCH (c1:Candidate {candidateId:"CAND1"}), (j1:JobPosting {jobId:"J100"})
MERGE (c1)-[:SEARCHED_FOR {at: datetime("2026-01-15T10:15:00"), query:"oracle junior"}]->(j1);
MATCH (c1:Candidate {candidateId:"CAND1"}), (j1:JobPosting {jobId:"J100"})
MERGE (c1)-[:APPLIED_TO {at: datetime("2026-01-15T10:40:00"), applicationId:"APP-7001", cvVersion:"v2"}]->(j1);
MATCH (c2:Candidate {candidateId:"CAND2"}), (j2:JobPosting {jobId:"J200"})
MERGE (c2)-[:SEARCHED_FOR {at: datetime("2026-01-15T11:05:00"), query:"java graz"}]->(j2);
5) Abfragen (ohne Lösung)
Kandidaten, die sich beworben haben.
Top-Jobs nach Anzahl Bewerbungen.
Jobs gesucht aber ohne Bewerbung.
Kandidaten, die alle JobPostings beworben haben.
Kandidaten, die in einer bestimmten Stadt gesucht haben.
Projekt 05 – Immobilienportal
1) Titel
Immobilien: Client – Listing
2) Kurzbeschreibung
Kunden suchen Immobilien und vereinbaren Besichtigungen. So lassen sich Nachfrage und Besichtigungen vergleichen.
3) Nodes & Relations
Nodes:
:Client(clientId, name, email),:Listing(listingId, type, city, price)Relations:
(:Client)-[:SEARCHED_FOR {at, query}]->(:Listing)(:Client)-[:SCHEDULED_VIEWING {at, viewingAt}]->(:Listing)
4) Befüllen (Cypher)
CREATE CONSTRAINT p05_client_id_unique IF NOT EXISTS
FOR (c:Client) REQUIRE c.clientId IS UNIQUE;
CREATE CONSTRAINT p05_listing_id_unique IF NOT EXISTS
FOR (l:Listing) REQUIRE l.listingId IS UNIQUE;
MERGE (c1:Client {clientId:"CL001"}) SET c1.name="Iris", c1.email="iris@example.com";
MERGE (c2:Client {clientId:"CL002"}) SET c2.name="Jonas", c2.email="jonas@example.com";
MERGE (l1:Listing {listingId:"L100"}) SET l1.type="Apartment", l1.city="Vienna", l1.price=450000;
MERGE (l2:Listing {listingId:"L200"}) SET l2.type="House", l2.city="Graz", l2.price=520000;
MERGE (l3:Listing {listingId:"L300"}) SET l3.type="Studio", l3.city="Vienna", l3.price=250000;
MATCH (c1:Client {clientId:"CL001"}), (l3:Listing {listingId:"L300"})
MERGE (c1)-[:SEARCHED_FOR {at: datetime("2026-01-16T12:10:00"), query:"vienna studio cheap"}]->(l3);
MATCH (c1:Client {clientId:"CL001"}), (l3:Listing {listingId:"L300"})
MERGE (c1)-[:SCHEDULED_VIEWING {at: datetime("2026-01-16T12:30:00"), viewingAt: datetime("2026-01-18T15:00:00")}]->(l3);
MATCH (c2:Client {clientId:"CL002"}), (l2:Listing {listingId:"L200"})
MERGE (c2)-[:SEARCHED_FOR {at: datetime("2026-01-16T09:05:00"), query:"house graz garden"}]->(l2);
5) Abfragen (ohne Lösung)
Kunden mit mindestens einer Besichtigung.
Top-Listings nach Besichtigungen.
Listings gesucht aber ohne Besichtigung.
Kunden, die alle Listings besichtigt haben.
Durchschnittspreis der Listings, die besichtigt wurden.
Projekt 06 – Restaurant-Reservierung
1) Titel
Gastronomie: Guest – Restaurant
2) Kurzbeschreibung
Gäste suchen Restaurants und reservieren Tische. Reservierungsdaten (Zeit, Gruppengröße) liegen auf der Beziehung.
3) Nodes & Relations
Nodes:
:Guest(guestId, name, email),:Restaurant(restaurantId, name, city, cuisine)Relations:
(:Guest)-[:SEARCHED_FOR {at, query}]->(:Restaurant)(:Guest)-[:RESERVED {at, reservationAt, partySize, reservationId}]->(:Restaurant)
4) Befüllen (Cypher)
CREATE CONSTRAINT p06_guest_id_unique IF NOT EXISTS
FOR (g:Guest) REQUIRE g.guestId IS UNIQUE;
CREATE CONSTRAINT p06_restaurant_id_unique IF NOT EXISTS
FOR (r:Restaurant) REQUIRE r.restaurantId IS UNIQUE;
MERGE (g1:Guest {guestId:"G001"}) SET g1.name="Kathi", g1.email="kathi@example.com";
MERGE (g2:Guest {guestId:"G002"}) SET g2.name="Lukas", g2.email="lukas@example.com";
MERGE (r1:Restaurant {restaurantId:"R100"}) SET r1.name="Trattoria Uno", r1.city="Vienna", r1.cuisine="Italian";
MERGE (r2:Restaurant {restaurantId:"R200"}) SET r2.name="Sushi Zen", r2.city="Vienna", r2.cuisine="Japanese";
MERGE (r3:Restaurant {restaurantId:"R300"}) SET r3.name="Steak House", r3.city="Graz", r3.cuisine="Steak";
MATCH (g1:Guest {guestId:"G001"}), (r2:Restaurant {restaurantId:"R200"})
MERGE (g1)-[:SEARCHED_FOR {at: datetime("2026-01-17T18:15:00"), query:"best sushi vienna"}]->(r2);
MATCH (g1:Guest {guestId:"G001"}), (r2:Restaurant {restaurantId:"R200"})
MERGE (g1)-[:RESERVED {at: datetime("2026-01-17T18:25:00"), reservationAt: datetime("2026-01-19T19:00:00"), partySize:2, reservationId:"RES-8101"}]->(r2);
MATCH (g2:Guest {guestId:"G002"}), (r3:Restaurant {restaurantId:"R300"})
MERGE (g2)-[:SEARCHED_FOR {at: datetime("2026-01-17T20:05:00"), query:"steak graz"}]->(r3);
5) Abfragen (ohne Lösung)
Top-Gäste nach Anzahl Reservierungen.
Restaurants gesucht aber nicht reserviert.
Reservierungen in einer bestimmten Stadt.
Gäste, die alle Restaurants reserviert haben.
Durchschnittliche PartySize pro Restaurant.
Projekt 07 – Musikshop
1) Titel
Musik: Listener – Album
2) Kurzbeschreibung
Hörer suchen Alben und kaufen sie. Auf der Kaufbeziehung stehen Bestellung und Preis zum Kaufzeitpunkt.
3) Nodes & Relations
Nodes:
:Listener(listenerId, name, email),:Album(albumId, title, genre, price)Relations:
(:Listener)-[:SEARCHED_FOR {at, query}]->(:Album)(:Listener)-[:PURCHASED {at, orderId, priceAtPurchase, currency}]->(:Album)
4) Befüllen (Cypher)
CREATE CONSTRAINT p07_listener_id_unique IF NOT EXISTS
FOR (l:Listener) REQUIRE l.listenerId IS UNIQUE;
CREATE CONSTRAINT p07_album_id_unique IF NOT EXISTS
FOR (a:Album) REQUIRE a.albumId IS UNIQUE;
MERGE (l1:Listener {listenerId:"LI01"}) SET l1.name="Mara", l1.email="mara@example.com";
MERGE (l2:Listener {listenerId:"LI02"}) SET l2.name="Nico", l2.email="nico@example.com";
MERGE (a1:Album {albumId:"A100"}) SET a1.title="Chill Beats", a1.genre="LoFi", a1.price=9.99;
MERGE (a2:Album {albumId:"A200"}) SET a2.title="Rock Legends", a2.genre="Rock", a2.price=12.99;
MERGE (a3:Album {albumId:"A300"}) SET a3.title="Classical Moods", a3.genre="Classical", a3.price=7.99;
MATCH (l1:Listener {listenerId:"LI01"}), (a1:Album {albumId:"A100"})
MERGE (l1)-[:SEARCHED_FOR {at: datetime("2026-01-18T09:15:00"), query:"lofi study"}]->(a1);
MATCH (l1:Listener {listenerId:"LI01"}), (a1:Album {albumId:"A100"})
MERGE (l1)-[:PURCHASED {at: datetime("2026-01-18T09:25:00"), orderId:"O-5001", priceAtPurchase:9.99, currency:"EUR"}]->(a1);
MATCH (l2:Listener {listenerId:"LI02"}), (a2:Album {albumId:"A200"})
MERGE (l2)-[:SEARCHED_FOR {at: datetime("2026-01-18T10:05:00"), query:"best rock compilation"}]->(a2);
5) Abfragen (ohne Lösung)
Top-Listener nach Anzahl Käufe.
Alben gesucht aber nicht gekauft.
Umsatz (Summe priceAtPurchase) pro Genre.
Listener, die alle Alben gekauft haben.
“Wer Album A gekauft hat, kaufte auch …”.
Projekt 08 – Arzttermin
1) Titel
Gesundheit: Patient – Doctor
2) Kurzbeschreibung
Patienten suchen Ärzte und buchen Termine. Terminzeit und Grund liegen auf der BOOKED-Beziehung.
3) Nodes & Relations
Nodes:
:Patient(patientId, name, email),:Doctor(doctorId, name, specialty, city)Relations:
(:Patient)-[:SEARCHED_FOR {at, query}]->(:Doctor)(:Patient)-[:BOOKED {at, appointmentAt, reason}]->(:Doctor)
4) Befüllen (Cypher)
CREATE CONSTRAINT p08_patient_id_unique IF NOT EXISTS
FOR (p:Patient) REQUIRE p.patientId IS UNIQUE;
CREATE CONSTRAINT p08_doctor_id_unique IF NOT EXISTS
FOR (d:Doctor) REQUIRE d.doctorId IS UNIQUE;
MERGE (p1:Patient {patientId:"PA01"}) SET p1.name="Olivia", p1.email="olivia@example.com";
MERGE (p2:Patient {patientId:"PA02"}) SET p2.name="Paul", p2.email="paul@example.com";
MERGE (d1:Doctor {doctorId:"DR10"}) SET d1.name="Dr. Weber", d1.specialty="Dermatology", d1.city="Vienna";
MERGE (d2:Doctor {doctorId:"DR20"}) SET d2.name="Dr. Huber", d2.specialty="Dentistry", d2.city="Vienna";
MERGE (d3:Doctor {doctorId:"DR30"}) SET d3.name="Dr. Moser", d3.specialty="Cardiology", d3.city="Graz";
MATCH (p1:Patient {patientId:"PA01"}), (d2:Doctor {doctorId:"DR20"})
MERGE (p1)-[:SEARCHED_FOR {at: datetime("2026-01-19T11:15:00"), query:"dentist vienna"}]->(d2);
MATCH (p1:Patient {patientId:"PA01"}), (d2:Doctor {doctorId:"DR20"})
MERGE (p1)-[:BOOKED {at: datetime("2026-01-19T11:35:00"), appointmentAt: datetime("2026-01-22T14:00:00"), reason:"checkup"}]->(d2);
MATCH (p2:Patient {patientId:"PA02"}), (d1:Doctor {doctorId:"DR10"})
MERGE (p2)-[:SEARCHED_FOR {at: datetime("2026-01-19T09:05:00"), query:"skin doctor"}]->(d1);
5) Abfragen (ohne Lösung)
Patienten mit mindestens einem Termin.
Top-Ärzte nach Anzahl BOOKED.
Ärzte gesucht aber nicht gebucht.
Patienten, die alle Ärzte gebucht haben.
Termine in einer bestimmten Stadt / Fachgebiet.
Projekt 09 – Hochschule
1) Titel
Uni: Student – Course
2) Kurzbeschreibung
Studierende suchen Kurse und schreiben sich ein. Einschreibung speichert Semester und Zeitpunkt.
3) Nodes & Relations
Nodes:
:Student(studentId, name, email),:Course(courseId, title, ects, level)Relations:
(:Student)-[:SEARCHED_FOR {at, query}]->(:Course)(:Student)-[:ENROLLED {at, semester}]->(:Course)
4) Befüllen (Cypher)
CREATE CONSTRAINT p09_student_id_unique IF NOT EXISTS
FOR (s:Student) REQUIRE s.studentId IS UNIQUE;
CREATE CONSTRAINT p09_course_id_unique IF NOT EXISTS
FOR (c:Course) REQUIRE c.courseId IS UNIQUE;
MERGE (s1:Student {studentId:"S001"}) SET s1.name="Quinn", s1.email="quinn@example.com";
MERGE (s2:Student {studentId:"S002"}) SET s2.name="Rita", s2.email="rita@example.com";
MERGE (c1:Course {courseId:"DB101"}) SET c1.title="Databases", c1.ects=6, c1.level="Beginner";
MERGE (c2:Course {courseId:"DB202"}) SET c2.title="Advanced SQL", c2.ects=5, c2.level="Intermediate";
MERGE (c3:Course {courseId:"GR301"}) SET c3.title="Graph Databases", c3.ects=5, c3.level="Advanced";
MATCH (s1:Student {studentId:"S001"}), (c3:Course {courseId:"GR301"})
MERGE (s1)-[:SEARCHED_FOR {at: datetime("2026-01-20T10:15:00"), query:"neo4j course"}]->(c3);
MATCH (s1:Student {studentId:"S001"}), (c3:Course {courseId:"GR301"})
MERGE (s1)-[:ENROLLED {at: datetime("2026-01-20T10:45:00"), semester:"2026S"}]->(c3);
MATCH (s2:Student {studentId:"S002"}), (c1:Course {courseId:"DB101"})
MERGE (s2)-[:SEARCHED_FOR {at: datetime("2026-01-20T09:05:00"), query:"database basics"}]->(c1);
5) Abfragen (ohne Lösung)
Top-Studierende nach Anzahl ENROLLED.
Kurse gesucht aber nicht belegt.
Studierende, die alle Kurse belegt haben.
Kurse nach Level sortiert mit Anzahl Einschreibungen.
“Wer Kurs A belegt, belegt auch …”.
Projekt 10 – Events/Tickets
1) Titel
Events: Attendee – Event
2) Kurzbeschreibung
Besucher suchen Events und kaufen Tickets. Ticketdaten stehen auf BOUGHT_TICKET.
3) Nodes & Relations
Nodes:
:Attendee(attendeeId, name, email),:Event(eventId, title, city, date)Relations:
(:Attendee)-[:SEARCHED_FOR {at, query}]->(:Event)(:Attendee)-[:BOUGHT_TICKET {at, ticketId, priceAtPurchase, currency}]->(:Event)
4) Befüllen (Cypher)
CREATE CONSTRAINT p10_attendee_id_unique IF NOT EXISTS
FOR (a:Attendee) REQUIRE a.attendeeId IS UNIQUE;
CREATE CONSTRAINT p10_event_id_unique IF NOT EXISTS
FOR (e:Event) REQUIRE e.eventId IS UNIQUE;
MERGE (a1:Attendee {attendeeId:"AT01"}) SET a1.name="Sara", a1.email="sara@example.com";
MERGE (a2:Attendee {attendeeId:"AT02"}) SET a2.name="Tom", a2.email="tom@example.com";
MERGE (e1:Event {eventId:"E100"}) SET e1.title="Jazz Night", e1.city="Vienna", e1.date=date("2026-02-10");
MERGE (e2:Event {eventId:"E200"}) SET e2.title="Tech Meetup", e2.city="Graz", e2.date=date("2026-02-12");
MERGE (e3:Event {eventId:"E300"}) SET e3.title="Art Expo", e3.city="Vienna", e3.date=date("2026-02-15");
MATCH (a1:Attendee {attendeeId:"AT01"}), (e1:Event {eventId:"E100"})
MERGE (a1)-[:SEARCHED_FOR {at: datetime("2026-01-21T12:15:00"), query:"jazz vienna"}]->(e1);
MATCH (a1:Attendee {attendeeId:"AT01"}), (e1:Event {eventId:"E100"})
MERGE (a1)-[:BOUGHT_TICKET {at: datetime("2026-01-21T12:20:00"), ticketId:"TCK-1001", priceAtPurchase:25.0, currency:"EUR"}]->(e1);
MATCH (a2:Attendee {attendeeId:"AT02"}), (e2:Event {eventId:"E200"})
MERGE (a2)-[:SEARCHED_FOR {at: datetime("2026-01-21T13:05:00"), query:"tech meetup graz"}]->(e2);
5) Abfragen (ohne Lösung)
Top-Events nach Ticketkäufen.
Besucher, die Tickets gekauft haben.
Events gesucht aber ohne Ticketkauf.
Besucher, die alle Events besucht/gekauft haben.
Umsatz pro Stadt.
Projekt 11 – Autovermietung
1) Titel
Car Rental: Renter – Car
2) Kurzbeschreibung
Kunden suchen Autos und mieten sie. Mietzeitraum und Preis sind Properties.
3) Nodes & Relations
Nodes:
:Renter(renterId, name, email),:Car(carId, model, class, dailyRate)Relations:
(:Renter)-[:SEARCHED_FOR {at, query}]->(:Car)(:Renter)-[:RENTED {at, bookingId, from, to, price, currency}]->(:Car)
4) Befüllen (Cypher)
CREATE CONSTRAINT p11_renter_id_unique IF NOT EXISTS
FOR (r:Renter) REQUIRE r.renterId IS UNIQUE;
CREATE CONSTRAINT p11_car_id_unique IF NOT EXISTS
FOR (c:Car) REQUIRE c.carId IS UNIQUE;
MERGE (r1:Renter {renterId:"RE01"}) SET r1.name="Ute", r1.email="ute@example.com";
MERGE (r2:Renter {renterId:"RE02"}) SET r2.name="Viktor", r2.email="viktor@example.com";
MERGE (c1:Car {carId:"CAR1"}) SET c1.model="VW Golf", c1.class="Compact", c1.dailyRate=45.0;
MERGE (c2:Car {carId:"CAR2"}) SET c2.model="BMW 3", c2.class="Sedan", c2.dailyRate=79.0;
MERGE (c3:Car {carId:"CAR3"}) SET c3.model="Skoda Fabia", c3.class="Compact", c3.dailyRate=39.0;
MATCH (r1:Renter {renterId:"RE01"}), (c3:Car {carId:"CAR3"})
MERGE (r1)-[:SEARCHED_FOR {at: datetime("2026-01-22T09:15:00"), query:"cheap compact car"}]->(c3);
MATCH (r1:Renter {renterId:"RE01"}), (c3:Car {carId:"CAR3"})
MERGE (r1)-[:RENTED {at: datetime("2026-01-22T09:30:00"), bookingId:"RENT-3001", from: date("2026-02-01"), to: date("2026-02-03"), price:78.0, currency:"EUR"}]->(c3);
MATCH (r2:Renter {renterId:"RE02"}), (c2:Car {carId:"CAR2"})
MERGE (r2)-[:SEARCHED_FOR {at: datetime("2026-01-22T10:05:00"), query:"sedan weekend"}]->(c2);
5) Abfragen (ohne Lösung)
Top-Kunden nach Anzahl RENTED.
Autos gesucht aber nicht gemietet.
Umsatz (Summe price) pro Fahrzeugklasse.
Kunden, die alle Autos gemietet haben.
Mietdauer (to-from) im Durchschnitt pro Auto.
Projekt 12 – Hotel
1) Titel
Hotel: Guest – Room
2) Kurzbeschreibung
Gäste suchen Zimmer und buchen sie. Buchung speichert Zeitraum und Preis.
3) Nodes & Relations
Nodes:
:HotelGuest(guestId, name, email),:Room(roomId, type, city, nightRate)Relations:
(:HotelGuest)-[:SEARCHED_FOR {at, query}]->(:Room)(:HotelGuest)-[:BOOKED {at, reservationId, checkIn, checkOut, price, currency}]->(:Room)
4) Befüllen (Cypher)
CREATE CONSTRAINT p12_guest_id_unique IF NOT EXISTS
FOR (g:HotelGuest) REQUIRE g.guestId IS UNIQUE;
CREATE CONSTRAINT p12_room_id_unique IF NOT EXISTS
FOR (r:Room) REQUIRE r.roomId IS UNIQUE;
MERGE (g1:HotelGuest {guestId:"HG01"}) SET g1.name="Wanda", g1.email="wanda@example.com";
MERGE (g2:HotelGuest {guestId:"HG02"}) SET g2.name="Xaver", g2.email="xaver@example.com";
MERGE (r1:Room {roomId:"RM10"}) SET r1.type="Single", r1.city="Vienna", r1.nightRate=89.0;
MERGE (r2:Room {roomId:"RM20"}) SET r2.type="Double", r2.city="Vienna", r2.nightRate=129.0;
MERGE (r3:Room {roomId:"RM30"}) SET r3.type="Suite", r3.city="Graz", r3.nightRate=199.0;
MATCH (g1:HotelGuest {guestId:"HG01"}), (r2:Room {roomId:"RM20"})
MERGE (g1)-[:SEARCHED_FOR {at: datetime("2026-01-23T11:15:00"), query:"double room vienna"}]->(r2);
MATCH (g1:HotelGuest {guestId:"HG01"}), (r2:Room {roomId:"RM20"})
MERGE (g1)-[:BOOKED {at: datetime("2026-01-23T11:40:00"), reservationId:"H-9001", checkIn: date("2026-02-10"), checkOut: date("2026-02-12"), price:258.0, currency:"EUR"}]->(r2);
MATCH (g2:HotelGuest {guestId:"HG02"}), (r3:Room {roomId:"RM30"})
MERGE (g2)-[:SEARCHED_FOR {at: datetime("2026-01-23T09:05:00"), query:"suite graz"}]->(r3);
5) Abfragen (ohne Lösung)
Top-Gäste nach Anzahl BOOKED.
Zimmer gesucht aber nicht gebucht.
Umsatz pro Stadt.
Gäste, die alle Zimmer gebucht haben.
Durchschnittliche Aufenthaltsdauer (checkOut-checkIn).
Projekt 13 – Versicherung
1) Titel
Versicherung: InsCustomer – Policy
2) Kurzbeschreibung
Kunden suchen Policen und schließen Verträge ab. Vertragsdaten liegen auf PURCHASED.
3) Nodes & Relations
Nodes:
:InsCustomer(customerId, name, email),:Policy(policyId, type, provider, monthlyPremium)Relations:
(:InsCustomer)-[:SEARCHED_FOR {at, query}]->(:Policy)(:InsCustomer)-[:PURCHASED {at, contractId, startDate, premium, currency}]->(:Policy)
4) Befüllen (Cypher)
CREATE CONSTRAINT p13_customer_id_unique IF NOT EXISTS
FOR (c:InsCustomer) REQUIRE c.customerId IS UNIQUE;
CREATE CONSTRAINT p13_policy_id_unique IF NOT EXISTS
FOR (p:Policy) REQUIRE p.policyId IS UNIQUE;
MERGE (c1:InsCustomer {customerId:"IC01"}) SET c1.name="Yara", c1.email="yara@example.com";
MERGE (c2:InsCustomer {customerId:"IC02"}) SET c2.name="Zeno", c2.email="zeno@example.com";
MERGE (p1:Policy {policyId:"PO10"}) SET p1.type="Car", p1.provider="SafeCo", p1.monthlyPremium=45.0;
MERGE (p2:Policy {policyId:"PO20"}) SET p2.type="Home", p2.provider="HomeSure", p2.monthlyPremium=29.0;
MERGE (p3:Policy {policyId:"PO30"}) SET p3.type="Travel", p3.provider="TripCare", p3.monthlyPremium=9.0;
MATCH (c1:InsCustomer {customerId:"IC01"}), (p1:Policy {policyId:"PO10"})
MERGE (c1)-[:SEARCHED_FOR {at: datetime("2026-01-24T10:15:00"), query:"car insurance cheap"}]->(p1);
MATCH (c1:InsCustomer {customerId:"IC01"}), (p1:Policy {policyId:"PO10"})
MERGE (c1)-[:PURCHASED {at: datetime("2026-01-24T10:45:00"), contractId:"CN-1001", startDate: date("2026-02-01"), premium:45.0, currency:"EUR"}]->(p1);
MATCH (c2:InsCustomer {customerId:"IC02"}), (p3:Policy {policyId:"PO30"})
MERGE (c2)-[:SEARCHED_FOR {at: datetime("2026-01-24T09:05:00"), query:"travel insurance"}]->(p3);
5) Abfragen (ohne Lösung)
Kunden mit mindestens einem Vertrag.
Top-Provider nach Anzahl PURCHASED.
Policen gesucht aber nicht gekauft.
Kunden, die alle Policen gekauft haben.
Durchschnittliche premium pro Policy-Typ.
Projekt 14 – Banking
1) Titel
Bank: BankClient – BankProduct
2) Kurzbeschreibung
Kunden suchen nach Bankprodukten und eröffnen sie (Konto/Karte/Sparen).
3) Nodes & Relations
Nodes:
:BankClient(clientId, name, email),:BankProduct(productId, name, type, feeMonthly)Relations:
(:BankClient)-[:SEARCHED_FOR {at, query}]->(:BankProduct)(:BankClient)-[:OPENED {at, accountRef, limit}]->(:BankProduct)
4) Befüllen (Cypher)
CREATE CONSTRAINT p14_client_id_unique IF NOT EXISTS
FOR (c:BankClient) REQUIRE c.clientId IS UNIQUE;
CREATE CONSTRAINT p14_product_id_unique IF NOT EXISTS
FOR (p:BankProduct) REQUIRE p.productId IS UNIQUE;
MERGE (c1:BankClient {clientId:"BC01"}) SET c1.name="Alina", c1.email="alina@example.com";
MERGE (c2:BankClient {clientId:"BC02"}) SET c2.name="Bruno", c2.email="bruno@example.com";
MERGE (p1:BankProduct {productId:"BP10"}) SET p1.name="Girokonto", p1.type="Account", p1.feeMonthly=0.0;
MERGE (p2:BankProduct {productId:"BP20"}) SET p2.name="Kreditkarte", p2.type="Card", p2.feeMonthly=3.0;
MERGE (p3:BankProduct {productId:"BP30"}) SET p3.name="Sparplan", p3.type="Savings", p3.feeMonthly=1.0;
MATCH (c1:BankClient {clientId:"BC01"}), (p2:BankProduct {productId:"BP20"})
MERGE (c1)-[:SEARCHED_FOR {at: datetime("2026-01-25T10:15:00"), query:"best credit card"}]->(p2);
MATCH (c1:BankClient {clientId:"BC01"}), (p2:BankProduct {productId:"BP20"})
MERGE (c1)-[:OPENED {at: datetime("2026-01-25T10:45:00"), accountRef:"CARD-7788", limit:1500}]->(p2);
MATCH (c2:BankClient {clientId:"BC02"}), (p1:BankProduct {productId:"BP10"})
MERGE (c2)-[:SEARCHED_FOR {at: datetime("2026-01-25T09:05:00"), query:"free account"}]->(p1);
5) Abfragen (ohne Lösung)
Top-Kunden nach Anzahl OPENED.
Produkte gesucht aber nicht eröffnet.
Verteilung der eröffneten Produkte nach Typ.
Kunden, die alle Produkte eröffnet haben.
Durchschnittliches Limit pro Kartenprodukt.
Projekt 15 – Mobilfunk
1) Titel
Telco: Subscriber – Plan
2) Kurzbeschreibung
Kunden suchen Tarife und schließen einen Vertrag ab. Laufzeit und Startdatum liegen auf SUBSCRIBED.
3) Nodes & Relations
Nodes:
:Subscriber(subscriberId, name, email),:Plan(planId, name, dataGb, monthly)Relations:
(:Subscriber)-[:SEARCHED_FOR {at, query}]->(:Plan)(:Subscriber)-[:SUBSCRIBED {at, contractMonths, startDate}]->(:Plan)
4) Befüllen (Cypher)
CREATE CONSTRAINT p15_sub_id_unique IF NOT EXISTS
FOR (s:Subscriber) REQUIRE s.subscriberId IS UNIQUE;
CREATE CONSTRAINT p15_plan_id_unique IF NOT EXISTS
FOR (p:Plan) REQUIRE p.planId IS UNIQUE;
MERGE (s1:Subscriber {subscriberId:"SUB1"}) SET s1.name="Carla", s1.email="carla@example.com";
MERGE (s2:Subscriber {subscriberId:"SUB2"}) SET s2.name="Denis", s2.email="denis@example.com";
MERGE (p1:Plan {planId:"PL10"}) SET p1.name="Basic", p1.dataGb=10, p1.monthly=9.9;
MERGE (p2:Plan {planId:"PL20"}) SET p2.name="Plus", p2.dataGb=50, p2.monthly=19.9;
MERGE (p3:Plan {planId:"PL30"}) SET p3.name="Max", p3.dataGb=200, p3.monthly=39.9;
MATCH (s1:Subscriber {subscriberId:"SUB1"}), (p2:Plan {planId:"PL20"})
MERGE (s1)-[:SEARCHED_FOR {at: datetime("2026-01-26T10:15:00"), query:"50gb plan"}]->(p2);
MATCH (s1:Subscriber {subscriberId:"SUB1"}), (p2:Plan {planId:"PL20"})
MERGE (s1)-[:SUBSCRIBED {at: datetime("2026-01-26T10:45:00"), contractMonths:24, startDate: date("2026-02-01")}]->(p2);
MATCH (s2:Subscriber {subscriberId:"SUB2"}), (p1:Plan {planId:"PL10"})
MERGE (s2)-[:SEARCHED_FOR {at: datetime("2026-01-26T09:05:00"), query:"cheap plan"}]->(p1);
5) Abfragen (ohne Lösung)
Top-Tarife nach Anzahl SUBSCRIBED.
Tarife gesucht aber nicht abgeschlossen.
Durchschnittliche Vertragslaufzeit.
Subscriber, die alle Tarife abgeschlossen haben.
Tarife mit Datenvolumen über X und Anzahl Abschlüsse.
Projekt 16 – Fitnessstudio
1) Titel
Gym: GymMember – GymClass
2) Kurzbeschreibung
Mitglieder suchen Kurse und buchen Plätze. Buchung enthält Termin und Buchungs-ID.
3) Nodes & Relations
Nodes:
:GymMember(memberId, name, email),:GymClass(classId, title, level, durationMin)Relations:
(:GymMember)-[:SEARCHED_FOR {at, query}]->(:GymClass)(:GymMember)-[:BOOKED {at, bookingId, classTime}]->(:GymClass)
4) Befüllen (Cypher)
CREATE CONSTRAINT p16_member_id_unique IF NOT EXISTS
FOR (m:GymMember) REQUIRE m.memberId IS UNIQUE;
CREATE CONSTRAINT p16_class_id_unique IF NOT EXISTS
FOR (c:GymClass) REQUIRE c.classId IS UNIQUE;
MERGE (m1:GymMember {memberId:"GM01"}) SET m1.name="Elena", m1.email="elena@example.com";
MERGE (m2:GymMember {memberId:"GM02"}) SET m2.name="Fritz", m2.email="fritz@example.com";
MERGE (c1:GymClass {classId:"CL10"}) SET c1.title="Yoga", c1.level="Beginner", c1.durationMin=60;
MERGE (c2:GymClass {classId:"CL20"}) SET c2.title="HIIT", c2.level="Advanced", c2.durationMin=45;
MERGE (c3:GymClass {classId:"CL30"}) SET c3.title="Pilates", c3.level="Intermediate", c3.durationMin=50;
MATCH (m1:GymMember {memberId:"GM01"}), (c1:GymClass {classId:"CL10"})
MERGE (m1)-[:SEARCHED_FOR {at: datetime("2026-01-27T10:15:00"), query:"yoga beginner"}]->(c1);
MATCH (m1:GymMember {memberId:"GM01"}), (c1:GymClass {classId:"CL10"})
MERGE (m1)-[:BOOKED {at: datetime("2026-01-27T10:45:00"), bookingId:"BK-1001", classTime: datetime("2026-01-28T18:00:00")}]->(c1);
MATCH (m2:GymMember {memberId:"GM02"}), (c2:GymClass {classId:"CL20"})
MERGE (m2)-[:SEARCHED_FOR {at: datetime("2026-01-27T09:05:00"), query:"hiit"}]->(c2);
5) Abfragen (ohne Lösung)
Top-Mitglieder nach Anzahl BOOKED.
Kurse gesucht aber nicht gebucht.
Kurse nach Level mit Buchungsanzahl.
Mitglieder, die alle Kurse gebucht haben.
Durchschnittliche Kursdauer der gebuchten Kurse.
Projekt 17 – Online Grocery
1) Titel
Grocery: Shopper – Item
2) Kurzbeschreibung
Kunden suchen Artikel und bestellen sie. Bestellbeziehung enthält Menge und Kaufpreis.
3) Nodes & Relations
Nodes:
:Shopper(shopperId, name, email),:Item(itemId, name, category, price)Relations:
(:Shopper)-[:SEARCHED_FOR {at, query}]->(:Item)(:Shopper)-[:ORDERED {at, orderId, quantity, priceAtPurchase, currency}]->(:Item)
4) Befüllen (Cypher)
CREATE CONSTRAINT p17_shopper_id_unique IF NOT EXISTS
FOR (s:Shopper) REQUIRE s.shopperId IS UNIQUE;
CREATE CONSTRAINT p17_item_id_unique IF NOT EXISTS
FOR (i:Item) REQUIRE i.itemId IS UNIQUE;
MERGE (s1:Shopper {shopperId:"SH01"}) SET s1.name="Greta", s1.email="greta@example.com";
MERGE (s2:Shopper {shopperId:"SH02"}) SET s2.name="Henry", s2.email="henry@example.com";
MERGE (i1:Item {itemId:"I100"}) SET i1.name="Milk", i1.category="Groceries", i1.price=1.49;
MERGE (i2:Item {itemId:"I200"}) SET i2.name="Bread", i2.category="Groceries", i2.price=1.99;
MERGE (i3:Item {itemId:"I300"}) SET i3.name="Apples", i3.category="Groceries", i3.price=2.49;
MATCH (s1:Shopper {shopperId:"SH01"}), (i3:Item {itemId:"I300"})
MERGE (s1)-[:SEARCHED_FOR {at: datetime("2026-01-28T10:15:00"), query:"fresh apples"}]->(i3);
MATCH (s1:Shopper {shopperId:"SH01"}), (i3:Item {itemId:"I300"})
MERGE (s1)-[:ORDERED {at: datetime("2026-01-28T10:45:00"), orderId:"ORD-9001", quantity:2, priceAtPurchase:2.49, currency:"EUR"}]->(i3);
MATCH (s2:Shopper {shopperId:"SH02"}), (i1:Item {itemId:"I100"})
MERGE (s2)-[:SEARCHED_FOR {at: datetime("2026-01-28T09:05:00"), query:"milk"}]->(i1);
5) Abfragen (ohne Lösung)
Top-Shopper nach Anzahl ORDERED.
Artikel gesucht aber nie bestellt.
Umsatz pro Kategorie (Summe quantity*priceAtPurchase).
Shopper, die alle Items bestellt haben.
“Basket”: wer Item A bestellt, bestellt auch welches Item?
Projekt 18 – IT Support
1) Titel
Support: SupportUser – KnowledgeArticle
2) Kurzbeschreibung
User suchen Wissensartikel und verwenden sie zur Lösung. Nutzung speichert “helpful” und “resolvedAt”.
3) Nodes & Relations
Nodes:
:SupportUser(userId, name, email),:KnowledgeArticle(articleId, title, topic, version)Relations:
(:SupportUser)-[:SEARCHED_FOR {at, query}]->(:KnowledgeArticle)(:SupportUser)-[:USED {at, helpful, resolvedAt}]->(:KnowledgeArticle)
4) Befüllen (Cypher)
CREATE CONSTRAINT p18_user_id_unique IF NOT EXISTS
FOR (u:SupportUser) REQUIRE u.userId IS UNIQUE;
CREATE CONSTRAINT p18_article_id_unique IF NOT EXISTS
FOR (a:KnowledgeArticle) REQUIRE a.articleId IS UNIQUE;
MERGE (u1:SupportUser {userId:"SU01"}) SET u1.name="Ivo", u1.email="ivo@example.com";
MERGE (u2:SupportUser {userId:"SU02"}) SET u2.name="Jana", u2.email="jana@example.com";
MERGE (a1:KnowledgeArticle {articleId:"KA10"}) SET a1.title="Reset Password", a1.topic="Account", a1.version=3;
MERGE (a2:KnowledgeArticle {articleId:"KA20"}) SET a2.title="VPN Setup", a2.topic="Network", a2.version=2;
MERGE (a3:KnowledgeArticle {articleId:"KA30"}) SET a3.title="Printer Fix", a3.topic="Hardware", a3.version=5;
MATCH (u1:SupportUser {userId:"SU01"}), (a2:KnowledgeArticle {articleId:"KA20"})
MERGE (u1)-[:SEARCHED_FOR {at: datetime("2026-01-29T10:15:00"), query:"vpn windows"}]->(a2);
MATCH (u1:SupportUser {userId:"SU01"}), (a2:KnowledgeArticle {articleId:"KA20"})
MERGE (u1)-[:USED {at: datetime("2026-01-29T10:45:00"), helpful:true, resolvedAt: datetime("2026-01-29T11:00:00")}]->(a2);
MATCH (u2:SupportUser {userId:"SU02"}), (a3:KnowledgeArticle {articleId:"KA30"})
MERGE (u2)-[:SEARCHED_FOR {at: datetime("2026-01-29T09:05:00"), query:"printer not working"}]->(a3);
5) Abfragen (ohne Lösung)
Top-Artikel nach Anzahl USED.
Artikel gesucht aber nie verwendet.
Erfolgsquote: Anteil helpful=true pro Artikel.
User, die alle Artikel verwendet haben.
Top-Topics nach Anzahl Suchanfragen.
Projekt 19 – Museum
1) Titel
Museum: Visitor – Exhibit
2) Kurzbeschreibung
Besucher suchen Ausstellungen und besuchen sie. Besuch speichert Dauer in Minuten.
3) Nodes & Relations
Nodes:
:Visitor(visitorId, name, email),:Exhibit(exhibitId, name, type, floor)Relations:
(:Visitor)-[:SEARCHED_FOR {at, query}]->(:Exhibit)(:Visitor)-[:VISITED {at, durationMin}]->(:Exhibit)
4) Befüllen (Cypher)
CREATE CONSTRAINT p19_visitor_id_unique IF NOT EXISTS
FOR (v:Visitor) REQUIRE v.visitorId IS UNIQUE;
CREATE CONSTRAINT p19_exhibit_id_unique IF NOT EXISTS
FOR (e:Exhibit) REQUIRE e.exhibitId IS UNIQUE;
MERGE (v1:Visitor {visitorId:"V001"}) SET v1.name="Karl", v1.email="karl@example.com";
MERGE (v2:Visitor {visitorId:"V002"}) SET v2.name="Lena", v2.email="lena@example.com";
MERGE (e1:Exhibit {exhibitId:"EX10"}) SET e1.name="Dinosaurs", e1.type="History", e1.floor=1;
MERGE (e2:Exhibit {exhibitId:"EX20"}) SET e2.name="Impressionists", e2.type="Art", e2.floor=2;
MERGE (e3:Exhibit {exhibitId:"EX30"}) SET e3.name="Space", e3.type="Science", e3.floor=3;
MATCH (v1:Visitor {visitorId:"V001"}), (e3:Exhibit {exhibitId:"EX30"})
MERGE (v1)-[:SEARCHED_FOR {at: datetime("2026-01-30T10:15:00"), query:"space exhibit"}]->(e3);
MATCH (v1:Visitor {visitorId:"V001"}), (e3:Exhibit {exhibitId:"EX30"})
MERGE (v1)-[:VISITED {at: datetime("2026-01-30T10:45:00"), durationMin:35}]->(e3);
MATCH (v2:Visitor {visitorId:"V002"}), (e2:Exhibit {exhibitId:"EX20"})
MERGE (v2)-[:SEARCHED_FOR {at: datetime("2026-01-30T09:05:00"), query:"impressionism"}]->(e2);
5) Abfragen (ohne Lösung)
Top-Ausstellungen nach VISITED.
Ausstellungen gesucht aber nicht besucht.
Durchschnittliche Besuchsdauer pro Ausstellung.
Besucher, die alle Ausstellungen besucht haben.
Ausstellungen pro Stockwerk mit Besuchszahlen.
Projekt 20 – E-Learning
1) Titel
E-Learning: Learner – Tutorial
2) Kurzbeschreibung
Lernende suchen Tutorials und schließen sie ab. Abschluss enthält Score und Abschlusszeit.
3) Nodes & Relations
Nodes:
:Learner(learnerId, name, email),:Tutorial(tutorialId, title, topic, level)Relations:
(:Learner)-[:SEARCHED_FOR {at, query}]->(:Tutorial)(:Learner)-[:COMPLETED {at, completedAt, score}]->(:Tutorial)
4) Befüllen (Cypher)
CREATE CONSTRAINT p20_learner_id_unique IF NOT EXISTS
FOR (l:Learner) REQUIRE l.learnerId IS UNIQUE;
CREATE CONSTRAINT p20_tutorial_id_unique IF NOT EXISTS
FOR (t:Tutorial) REQUIRE t.tutorialId IS UNIQUE;
MERGE (l1:Learner {learnerId:"LE01"}) SET l1.name="Milan", l1.email="milan@example.com";
MERGE (l2:Learner {learnerId:"LE02"}) SET l2.name="Nora", l2.email="nora@example.com";
MERGE (t1:Tutorial {tutorialId:"TU10"}) SET t1.title="SQL Basics", t1.topic="Databases", t1.level="Beginner";
MERGE (t2:Tutorial {tutorialId:"TU20"}) SET t2.title="Neo4j Intro", t2.topic="Graphs", t2.level="Beginner";
MERGE (t3:Tutorial {tutorialId:"TU30"}) SET t3.title="Indexing", t3.topic="Databases", t3.level="Intermediate";
MATCH (l1:Learner {learnerId:"LE01"}), (t2:Tutorial {tutorialId:"TU20"})
MERGE (l1)-[:SEARCHED_FOR {at: datetime("2026-01-31T10:15:00"), query:"graph database tutorial"}]->(t2);
MATCH (l1:Learner {learnerId:"LE01"}), (t2:Tutorial {tutorialId:"TU20"})
MERGE (l1)-[:COMPLETED {at: datetime("2026-01-31T10:45:00"), completedAt: datetime("2026-01-31T12:00:00"), score:92}]->(t2);
MATCH (l2:Learner {learnerId:"LE02"}), (t1:Tutorial {tutorialId:"TU10"})
MERGE (l2)-[:SEARCHED_FOR {at: datetime("2026-01-31T09:05:00"), query:"learn sql"}]->(t1);
5) Abfragen (ohne Lösung)
Top-Learner nach Anzahl COMPLETED.
Tutorials gesucht aber nicht abgeschlossen.
Durchschnittlicher Score pro Tutorial.
Learner, die alle Tutorials abgeschlossen haben.
Top-Topics nach Anzahl Abschlüsse.