xyzDB

Declaring data

xyTalk is the whole interface — there is no separate schema language. Declare a space, an identity, and how data co-locates; the engine owns the rest.

Hello world

A space, an identity, two linked records, one traversal.

LOBE "workspace"
ANCHOR "code" UNIQUE IN "workspace"

PUT {_type: "Company", code: "ACME", name: "Acme Corp"} IN "workspace"
PUT {_type: "Project", project_id: "P1", budget: 50000} IN "workspace"
    LINK TO "workspace" WHERE code = "ACME" AS "owner"

FIND "workspace" WHERE code = "ACME" | PULL depth=2

Writing records

PUT writes one record; PUT BATCH writes up to 10,000 atomically. Add ON CONFLICT UPDATE to upsert on an anchor.

PUT BATCH IN "creditos" [
  {*rfc: "ACME-001", _type: "Installment", amount: 1000},
  {*rfc: "ACME-001", _type: "Installment", amount: 1500}
]

Declaring gravity

A bare *field in PUT is sugar for raw gravity. GRAVITY BY declares it per lobe — raw, normalized, or composite.

GRAVITY BY rfc IN "creditos"            # raw
GRAVITY BY lower(email) IN "users"     # normalized
GRAVITY BY (region, tier) IN "accounts"  # composite

LINK adds a _link_<relation> field (the target LID) to each source record, so PULL can traverse it.

LINK "pagos" WHERE credito = "C-1" TO "creditos" WHERE id = "C-1" AS "credit"

Ghosts & vector fields

CREATE GHOST declares like the query it serves — a pipeline ending in TAKE BY (the order step is mandatory); the classic ORDER BY clause form is a live alias of the same statement.

CREATE GHOST "top_exposure_by_rfc" FROM "creditos"
    WHERE _type = "Credit"
    | GROUP BY rfc
    | AGGREGATE count(), sum(monto)
    | TAKE BY sum(monto) DESC

VECTOR embedding IN "memories"

A ghost ordered by a declared metric keeps a metric-ordered rollup, so a matching TAKE n BY reads the first N in O(N) instead of O(M). Manage ghosts with REFRESH GHOST / DROP GHOST.