Database API
So far, all the queries and mutations that have been discussed were specific to the stored and managed developer or user-created objects. However, that is only one aspect of DefraDB's GraphQL API. The other part of DefraDB GraphQL API is the auxiliary APIs, which include MerkleCRDT Traversal, Schema Management, and more.
MerkleCRDTs
All objects in DefraDB are stored in MerkleCRDTs (see Merkle CRDT Guide). These MerkleCRDTs are represented as a series of small updates connected in a MerkleDAG. The MerkleDAG is a Merklized version of a DAG (Directed Acyclical Graph), which means that each node in the DAG references a parent node through some kind of Content Identifier (CID).
The image below shows an example structure of a MerkleDAG.
The Head
CID represents the "current" or "latest" state of a MerkleDAG.
DefraDB allows you to query, traverse, and validate the DAG structure, allowing for self-verifying data structures.
In DefraDB Database API, DAG nodes are represented as Commit
, CommitLink
, and Delta
types. They are defined as shown below:
# Commit is an individual node in a CRDTs MerkleDAG
type Commit {
cid: String // cid is the Content Identifier of this commit
height: Int // height is the incremental version of the current commit
delta: Delta // delta is the delta-state update generated by a CRDT mutation
previous: [Commit] // previous is the links to the previous node in the MerkleDAG
links: [CommitLink] // links are any additional commits this commit may reference.
}
# CommitLink is a named link to a commit
type CommitLink {
name: String // name is the name of the CommitLink
commit: Commit // commit is the linked commit
}
# Delta is the differential state change from one node to another
type Delta {
payload: String // payload is a base64 encoded byte-array.
}
To query the latest commit of an object (with id: '123'):
query {
latestCommits(docid: "123") {
cid
height
delta {
payload
}
}
}
To query all the commits of an object (with id: '123'):
query {
allCommits(docid: "123") {
cid
height
delta {
payload
}
}
}
To query a specific commit:
query {
Commits(cid: 'Qm123') {
cid
height
delta {
payload
}
}
}
In addition to using Commits
specific queries, include commit version sub-fields in object queries.
query {
User {
_key
name
age
_version {
cid
height
}
}
}
The above example shows how to query for the additional _version
field that is generated automatically for each added schema type. The _version
has the same execution as latestCommits
.
Both _version
and latestCommits
return an array of Commits
types because the HEAD
of the MerkleDAG can point to more than one DAG node. This is caused by two concurrent updates to the DAG at the same height. The DAG usually has a single head. However, it can also have multiple heads.
Commits queries also work with aggregates, grouping, limit, offset, order, dockey, cid, and depth There is __typename introspection keyword that works on all queries that does not appear to be documented anywhere, for example:
commits(dockey: "bae-52b9170d-b77a-5887-b877-cbdbb99b009f") {
cid
__typename
}