You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Overlay sampling relationships onto the existing knowledge graph, revealing the hidden connections between tracks. "Amen, Brother by The Winstons has been sampled 4,532 times — here's the family tree." Sampling is one of music's most fascinating relationship types and a natural extension of the graph model.
Since Discogs itself has limited sampling data, this feature integrates with external sources (WhoSampled, MusicBrainz recording relationships) and maps them onto existing graph nodes. The result: a new SAMPLED relationship type that enables sample chain exploration, breakbeat archaeology, and producer lineage tracking.
Track nodes are optional in Phase 1 — sample relationships can connect at the Release level initially, with track metadata stored as relationship properties.
Derived Relationships
(a1:Artist)-[:SAMPLED_ARTIST]->(a2:Artist) — materialized view for artist-level queries
Sample chain depth: how many generations of sampling separate two releases
Proposed Endpoints
API Endpoints (api/routers/samples.py)
Endpoint
Description
GET /api/samples/{release_id}
Samples used in this release and releases that sample it
GET /api/samples/{release_id}/chain
Full sample chain — recursive upstream and downstream
GET /api/samples/{release_id}/tree
Tree visualization data for sample lineage
GET /api/samples/most-sampled
Most-sampled releases in the database
GET /api/samples/artist/{artist_id}
All sampling relationships for an artist's discography
GET /api/samples/search
Search for sampling connections between two entities
POST /api/samples/submit
Submit a new sampling relationship (authenticated, queued for moderation)
Response Shape (example: release samples)
{
"release_id": 456,
"title": "It Takes a Nation of Millions to Hold Us Back",
"artist": "Public Enemy",
"samples_used": [
{
"release_id": 789,
"title": "Funky Drummer",
"artist": "James Brown",
"track_from": "Bring the Noise",
"track_to": "Funky Drummer",
"source": "whosampled",
"confirmed": true
}
],
"sampled_by": [
{
"release_id": 1011,
"title": "...",
"artist": "...",
"track_from": "...",
"track_to": "...",
"year": 2005
}
],
"stats": {
"total_samples_used": 45,
"total_sampled_by": 12,
"chain_depth_upstream": 3,
"chain_depth_downstream": 2
}
}
Sample Search — autocomplete search for a release, shows upstream (what it samples) and downstream (what sampled it) as a bidirectional list
Sample Tree Visualization — D3.js tree/radial layout showing the full sample chain from a root release. Nodes colored by decade, sized by how many times they were sampled
Most Sampled Leaderboard — ranked list of the most-sampled releases in the database, with sample count and genre
Submit Sample (authenticated) — form to submit a new sampling relationship with source release, target release, track names, and evidence URL
Integration with Existing Explore Pane
When viewing a release/artist node in the graph, show a "Samples" badge if sampling relationships exist
"Show sample connections" toggle in the graph view to overlay sampling edges (distinct color/style)
Sample relationships included in path finder results
Overview
Overlay sampling relationships onto the existing knowledge graph, revealing the hidden connections between tracks. "Amen, Brother by The Winstons has been sampled 4,532 times — here's the family tree." Sampling is one of music's most fascinating relationship types and a natural extension of the graph model.
Since Discogs itself has limited sampling data, this feature integrates with external sources (WhoSampled, MusicBrainz recording relationships) and maps them onto existing graph nodes. The result: a new
SAMPLEDrelationship type that enables sample chain exploration, breakbeat archaeology, and producer lineage tracking.Data Sources
Primary: WhoSampled (web scraping / manual import)
Secondary: MusicBrainz Recording Relationships
samples_materialandis_sampled_byTertiary: Community Contributions
Graph Model Extension
New Relationship
New Node (optional, for track-level granularity)
Track nodes are optional in Phase 1 — sample relationships can connect at the Release level initially, with track metadata stored as relationship properties.
Derived Relationships
(a1:Artist)-[:SAMPLED_ARTIST]->(a2:Artist)— materialized view for artist-level queriesProposed Endpoints
API Endpoints (
api/routers/samples.py)GET /api/samples/{release_id}GET /api/samples/{release_id}/chainGET /api/samples/{release_id}/treeGET /api/samples/most-sampledGET /api/samples/artist/{artist_id}GET /api/samples/searchPOST /api/samples/submitResponse Shape (example: release samples)
{ "release_id": 456, "title": "It Takes a Nation of Millions to Hold Us Back", "artist": "Public Enemy", "samples_used": [ { "release_id": 789, "title": "Funky Drummer", "artist": "James Brown", "track_from": "Bring the Noise", "track_to": "Funky Drummer", "source": "whosampled", "confirmed": true } ], "sampled_by": [ { "release_id": 1011, "title": "...", "artist": "...", "track_from": "...", "track_to": "...", "year": 2005 } ], "stats": { "total_samples_used": 45, "total_sampled_by": 12, "chain_depth_upstream": 3, "chain_depth_downstream": 2 } }Response Shape (example: chain)
{ "root": { "release_id": 456, "title": "Funky Drummer", "artist": "James Brown", "year": 1970 }, "generations": [ { "depth": 1, "releases": [ {"release_id": 789, "title": "It Takes a Nation...", "artist": "Public Enemy", "year": 1988}, {"release_id": 790, "title": "3 Feet High and Rising", "artist": "De La Soul", "year": 1989} ] }, { "depth": 2, "releases": [ {"release_id": 1011, "title": "...", "artist": "...", "year": 2003} ] } ], "stats": { "total_descendants": 4532, "max_depth": 5, "most_active_decade": "1990s" } }Explore UI — "Samples" Pane
Add a Samples pane to the Explore sidebar.
Layout
Integration with Existing Explore Pane
Integration Points
samples_materialrelationships during enrichmentget_sample_chainandget_most_sampledtoolsImplementation Notes
MATCH path = (r)-[:SAMPLED*1..5]->(root)— cap depth to prevent expensive traversalsSAMPLEDrelationship for performant lookupsAcceptance Criteria