Skip to content
HN On Hacker News ↗

DuckPGQ

▲ 64 points • 11 comments • by rzk • 4mo ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this document is primarily human-written, with some AI-generated and AI-assisted content detected

15 %

AI likelihood · overall

Mixed
81% human-written 5% AI-generated
SEGMENTS · HUMAN 5 of 7
SEGMENTS · AI 1 of 7
WORD COUNT 897
PEAK AI % 82% · §7
Analyzed
Jul 24
backend: pangram/v3.3
Segments scanned
7 windows
avg 128 words each
Distribution
81 / 5%
human / AI fraction
Verdict
Mixed
Pangram v3.3

Article text · 897 words · 7 segments analyzed

Human AI-generated
§1 Mixed · 59%

DuckPGQ is a DuckDB community extension for graph workloads that supports the SQL/PGQ standard. Leveraging the power of DuckDB to bring high-performance, SQL-based graph query capabilities directly to your analytical workflows.

Install and Load DuckPGQ CLIPythonNodeJSRJava

INSTALL duckpgq FROM community; LOAD duckpgq;

import duckdb conn = duckdb.connect() conn.install_extension("duckpgq", repository="community") conn.load_extension("duckpgq")

import { DuckDBInstance } from '@duckdb/node-api'; const instance = await DuckDBInstance.create(); const connection = await instance.connect(); await connection.run("INSTALL duckpgq FROM community"); await connection.run("LOAD duckpgq");

library(duckdb) con <- dbConnect(duckdb()) dbExecute(con, "INSTALL duckpgq FROM community") dbExecute(con, "LOAD duckpgq")

Connection conn = DriverManager.getConnection("jdbc:duckdb:"); Statement st = conn.createStatement(); st.execute("INSTALL duckpgq FROM community"); st.execute("LOAD duckpgq");

Key Features

SQL/PGQ Standard Supports graph pattern matching with SQL/PGQ, following the SQL:2023 standard. High Performance Leverages DuckDB for efficient, in-process graph analytics.

§2 Human · 8%

Easy To Install Seamlessly integrate with DuckDB through a simple setup process, requiring no dependencies. Open Source Community-driven, extensible, and free to use.

Explore DuckPGQ Across Domains Social NetworksAirline DataFinancial Data

Setup ATTACH 'https://github.com/Dtenwolde/duckpgq-docs/raw/refs/heads/main/datasets/snb.duckdb';

use snb; install duckpgq from community; load duckpgq;

CREATE or replace PROPERTY GRAPH snb VERTEX TABLES ( Person, Forum ) EDGE TABLES ( Person_knows_person SOURCE KEY (Person1Id) REFERENCES Person (id) DESTINATION KEY (Person2Id) REFERENCES Person (id) LABEL knows, Forum_hasMember_Person SOURCE KEY (ForumId) REFERENCES Forum (id) DESTINATION KEY (PersonId) REFERENCES Person (id) LABEL hasMember );

Shortest Path QueryFind Mutual FriendsMost Popular PeopleForum count of the most-followed person

-- find the shortest path from one person to all other persons FROM GRAPH_TABLE (snb MATCH p = ANY SHORTEST (p1:person WHERE p1.id = 14)-[k:knows]->*(p2:person) COLUMNS (p1.id, p2.id as other_person_id, element_id(p), path_length(p)) );

-- Find mutual friends between two users FROM GRAPH_TABLE (snb MATCH (p1:Person WHERE p1.id = 16)-[k:knows]->(p2:Person)<-[k2:knows]-(p3:Person WHERE p3.id = 32) COLUMNS (p2.firstName) );

-- Find the 3 most popular people FROM GRAPH_TABLE (snb MATCH (follower:Person)-[follows:knows]->(person:Person) COLUMNS (person.id AS personID, person.firstname,

§3 Human · 1%

person.lastname, follower.id AS followerID) ) SELECT personID, firstname, lastname, COUNT(followerID) AS numFollowers GROUP BY ALL ORDER BY numFollowers DESC LIMIT 3;

-- Number of forums posted on by the most followed person WITH mfp AS ( FROM GRAPH_TABLE (snb MATCH (follower:Person)-[follows:knows]->(person:Person) COLUMNS (person.id AS personID, person.firstname, follower.id AS followerID) ) SELECT personID, firstname, COUNT(followerID) AS numFollowers GROUP BY ALL ORDER BY numFollowers DESC LIMIT 1 ) FROM mfp, GRAPH_TABLE (snb MATCH (person:Person)<-[fhm:hasMember]-(f:Forum) COLUMNS (person.id AS personID, f.id as forumId) ) mem SELECT mfp.personID, mfp.firstname, mfp.numFollowers, count(mem.forumId) forumCount WHERE mfp.personID = mem.personID GROUP BY ALL;

Setup ATTACH 'https://github.com/Dtenwolde/duckpgq-docs/raw/refs/heads/airline-data/datasets/airline-data-small.duckdb' as airline;

use airline; install duckpgq from community; load duckpgq;

CREATE PROPERTY GRAPH flight_graph VERTEX TABLES ( aircrafts_data, airports_data, bookings, flights, tickets, seats ) EDGE TABLES ( route SOURCE KEY (departure_airport) REFERENCES airports_data(airport_code) DESTINATION KEY (arrival_airport) REFERENCES airports_data(airport_code), ticket_flights SOURCE KEY (ticket_no) REFERENCES tickets(ticket_no)

§4 Human · 0%

DESTINATION KEY (flight_id) REFERENCES flights(flight_id), bookings_tickets SOURCE KEY (book_ref) REFERENCES bookings(book_ref) DESTINATION KEY (ticket_no) REFERENCES tickets(ticket_no), boarding_passes SOURCE KEY (ticket_no) REFERENCES tickets(ticket_no) DESTINATION KEY (seat_no) REFERENCES seats(seat_no) );

Shortest Route Between AirportsMost Expensive Seats on Average

FROM ( SELECT unnest(flights) AS flights FROM GRAPH_TABLE ( flight_graph MATCH o = ANY SHORTEST (a:airports_data WHERE a.airport_code = 'UKX') -[fr:route]->* (a2:airports_data WHERE a2.airport_code = 'CNN') COLUMNS (edges(o) AS flights) ) ) JOIN route f ON f.rowid = flights;

FROM GRAPH_TABLE ( flight_graph MATCH (b:bookings)-[bt:bookings_tickets]->(t:tickets)-[bp:boarding_passes]->(s:seats) ) SELECT round(avg(total_amount), 2) avg_amount, seat_no GROUP BY seat_no ORDER BY avg_amount DESC;

Setup ATTACH 'https://github.com/Dtenwolde/duckpgq-docs/raw/refs/heads/main/datasets/finbench.duckdb' AS finbench; use finbench; INSTALL duckpgq FROM community; LOAD duckpgq;

CREATE OR REPLACE PROPERTY GRAPH finbench VERTEX TABLES ( Account, Company, Loan, Medium, Person ) EDGE TABLES ( AccountRepayLoan SOURCE KEY (accountId) REFERENCES Account (accountId) DESTINATION KEY (loanId)

§5 Human · 1%

REFERENCES Loan (loanId) LABEL repay, AccountTransferAccount SOURCE KEY (fromId) REFERENCES Account (accountId) DESTINATION KEY (toId) REFERENCES Account (AccountId) LABEL transfer, AccountWithdrawAccount SOURCE KEY (fromId) REFERENCES Account (accountId) DESTINATION KEY (toId) REFERENCES Account (AccountId) LABEL withdraw, CompanyApplyLoan SOURCE KEY (companyId) REFERENCES Company (companyId) DESTINATION KEY (loanId) REFERENCES Loan (loanId) LABEL companyApply, CompanyGuaranteeCompany SOURCE KEY (fromId) REFERENCES Company (companyId) DESTINATION KEY (toId) REFERENCES Company (companyId) LABEL companyGuarantee, CompanyInvestCompany SOURCE KEY (investorId) REFERENCES Company (companyId) DESTINATION KEY (companyId) REFERENCES Company (companyId) LABEL companyInvest, CompanyOwnAccount SOURCE KEY (companyId) REFERENCES Company (companyId) DESTINATION KEY (accountId) REFERENCES Account (accountId) LABEL companyOwn, LoanDepositAccount SOURCE KEY (loanId) REFERENCES Loan (loanId) DESTINATION KEY (accountId) REFERENCES Account (accountId) LABEL deposit, MediumSignInAccount SOURCE KEY (mediumId) REFERENCES Medium (mediumId) DESTINATION KEY (accountId) REFERENCES Account (accountId) LABEL signIn, PersonApplyLoan SOURCE KEY (personId) REFERENCES Person (personId) DESTINATION KEY (loanId) REFERENCES Loan (loanId) LABEL

§6 Human · 8%

personApply, PersonGuaranteePerson SOURCE KEY (fromId) REFERENCES Person (personId) DESTINATION KEY (toId) REFERENCES Person (personId) LABEL personGuarantee, PersonInvestCompany SOURCE KEY (investorId) REFERENCES Person (personId) DESTINATION KEY (companyId) REFERENCES Company (companyId) LABEL personInvest, PersonOwnAccount SOURCE KEY (personId) REFERENCES Person (personId) DESTINATION KEY (accountId) REFERENCES Account (accountId) LABEL personOwn );

Find blocked accounts via transfersFilter high-value transfers by time

FROM GRAPH_TABLE ( finbench MATCH (src:Account where src.accountId = 16607023625929101) <-[e1:transfer]-(mid:Account) -[e2:transfer]->(dst:Account where dst.isBlocked = true) COLUMNS (src.accountId as src_id, dst.accountId as dst_id) ) SELECT src_id, dst_id WHERE src_Id <> dst_id;

FROM GRAPH_TABLE ( finbench MATCH (src:Account)-[e:Transfer]->(dst:Account) WHERE '2022-07-13 09:18:33.137' < e.createtime AND e.createtime < '2022-09-03 02:31:47.812' AND e.amount > 4829783 );

Daniël ten Wolde Lead Developer of DuckPGQ and PhD student at CWI specializing in graph analytics and database systems.

§7 AI · 82%

WIP Disclaimer DuckPGQ is currently a research project and still a work in progress. While we encourage you to explore and experiment with it, please be aware that there may be bugs, incomplete features, or unexpected behaviour. We greatly appreciate any feedback or bug reports that help us improve and evolve the extension. Feel free to share your experiences!