Same question. Less ceremony.

Every query language answers questions. The difference is how much of what you write is the question — and how much is plumbing.

“Get tracks by Miles Davis — their titles, creators, and reviews.”

SPOQE

{:pull
  [(tracks-by "Miles Davis")
   :dc/title
   {:dc/creator [:foaf/name]}
   {:review/has
     [:review/stars
      :review/text]}]}

Tracks from a triplestore. Reviews from Postgres. One query.

Here's what SPOQE generates from that.

To the triplestore

generated SPARQL
PREFIX dc:   <http://purl.org/dc/elements/1.1/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT ?track ?title ?name
WHERE {
  ?track  dc:creator  ?artist .
  ?artist foaf:name  "Miles Davis" .
  ?track  dc:title   ?title .
  ?artist foaf:name  ?name .
}
domain words

To Postgres

generated SQL
SELECT stars, text
FROM reviews
WHERE track_id IN (
  42, 87
)
domain words

You write this. It means that.

Name a pattern, reuse it everywhere. The definition is inspectable — no hidden magic.

Define once

;; A reusable pattern
(defn tracks-by [name]
  {:from   [?t :mo/Track]
   :filter (= [:dc/creator
              :foaf/name] name)})

Use everywhere

(tracks-by "Miles Davis")
(tracks-by "John Coltrane")
(tracks-by "Thelonious Monk")
;; See exactly what happens
(explain
  (tracks-by "Miles Davis"))

The ceremony still happens — SPOQE generates the SPARQL and SQL.
Run (explain ...) to see every step. Copy it, modify it, run it directly.

The vocabulary was always right.
The grammar was the problem.

The semantic web gave us precise, reusable names for everything. SPOQE gives those names a language that doesn't make you stutter.