Skip to main content
Version: 1.0 RC1 (Latest)

Database collections

Collections represent groups of documents with similar structures, like tables for SQL databases. They create structure in an otherwise chaotic world. Every document created in DefraDB belongs to a collection.

A collection has a name (ex. Book) and a number of typed fields (ex. title: String).

An example collection
type Book {
title: String
plot: String
rating: Float
}

Field types

Fields can be of different types:

  • Int: A signed 32‐bit integer.
  • Float: A signed double-precision floating-point value.
  • String: A UTF‐8 character sequence.
  • Boolean: true or false.
  • ID: A unique identifier. Although the ID type is serialized in the same way as a String, defining it as an ID communicates that it is not intended to be human‐readable.
  • DateTime: (ex. 2017-07-23T03:46:56.647Z)
  • JSON: A JSON string (ex. { "privacy": {"is": "sexy"} }). JSON fields get specially indexed.
  • Blob: A hex string (ex. 00FF).
  • List: An array of another type (ex. [String]). Lists can not be nested.

Create collections

You can create a collection with either the CLI command defradb client collection add, the HTTP API endpoint /collections, or the method AddCollection.

defradb client collection add '
type Book {
title: String
plot: String
rating: Float
}
'

Relationships

To create a relationship between two types, define a field having the other side of the relationship as type.

The way in which you define relationships depends on their kind:

  • One-to-one – Each document of one type is linked to one and only one document of the other type.
  • One-to-many – Each document of one type is linked to multiple documents of the other type.
  • Many-to-many – Each document of one type is linked to multiple documents of the other type.

See also: Create documents with relationships and Query the database.

One-to-one

One-to-one relationships are such that each document of one type is linked to one and only one document of another type.

In practice, type A defines a field of type B, and type B defines a field of type A. For example, there's a one-to-one relationship between Husband and Wife (disregarding avant-garde polyamorous relationships).

Type Husband with 1:1 relationship with Wife
type Husband {
name: String
wife: Wife
}

type Wife {
name: String
husband: Husband @primary @index(unique: true)
}
  • @primary – This side stores a direct pointer to the other end of the relationship, resulting in faster queries. In the example above, Wife contains a (implicit) field _husbandID, so retrieving a wife's husband is quick. On the other hand, documents of type Husband do not contain any pointer to the relative Wife, so a collection scan is needed to retrieve a husband's wife. Which side should be primary depends on your query patterns.
  • index(unique: true) – Creates a unique index on _husbandID, making the relationship one-to-one.
warning

There's currently no validation on the type when creating documents with relationships. It is the client's responsibility to validate that the Wife.husbandID is populated with the docID of a Husband document. It's up to you to marry humans.

One-to-many

One-to-many relationships link one document of one type with many documents of another type. Type A defines a field of type B, whereas type B defines a field of type [A] (list of A). For example, each book is written by one author, whereas one author can write multiple books.

Type Book with 1:many relationship with Author
type Book {
title: String
author: Author
}

type Author {
name: String
authoredBooks: [Book]
}
warning

There's currently no validation on the type when creating documents with relationships. It is the client's responsibility to validate that the Book.authorID is populated with the docID of a Author document.

Many-to-many

Many-to-many relationships link multiple documents of one type to multiple documents of another type. In DefraDB, you achieve this with two one-to-many relationships and a join type. For example, a student can enroll in many courses, and a course can have many students enrolled.

Type Student with many:many relationship with Course
type Student {
name: String
age: Int
enrollment: [Enrollment]
}

type Course {
title: String
code: String
enrollment: [Enrollment]
}

type Enrollment {
student: Student
course: Course
}

Rename a relationship field

By default,

Type Husband with 1:1 relationship with Wife
type Husband {
name: String
wife: Wife
}

type Wife {
name: String
husband: Husband @primary @index(unique: true)
}

Show collections

To see all collections available on an instance, use the CLI command defradb client collection describe or the HTTP API endpoint /collections.

defradb client collection describe
tip

Use the --name parameter to request a specific collection by its name.

Result
[
{
"Name": "Book",
"VersionID": "bafyreihqndwux4ewnlvmtcfvptikfvzu76tri2i5x4nbpiqh3hskxmagcm",
"CollectionID": "bafyreihqndwux4ewnlvmtcfvptikfvzu76tri2i5x4nbpiqh3hskxmagcm",
"CollectionSet": null,
"Query": null,
"PreviousVersion": null,
"Fields": [
{
"FieldID": "bafyreihqzhiz3iwro4jozp6kphq4sosg6ccoqcbiaf7rg5dmvea7aux55a",
"Name": "_docID",
"Kind": 1,
"Typ": 0,
"RelationName": null,
"IsPrimary": false,
"DefaultValue": null,
"Size": 0
},
{
"FieldID": "bafyreiguuxtuepj5vji3oe5j6lyhwqi5izm4all3gav7ppvgj35hxklrte",
"Name": "_authorID",
"Kind": 1,
"Typ": 1,
"RelationName": "book_person",
"IsPrimary": true,
"DefaultValue": null,
"Size": 0
},
{
"FieldID": "bafyreibhohsw25uzzzbzs2awta43ql5oo6anry3rxdcuj2n3hlfbjmifse",
"Name": "author",
"Kind": {
"Array": false,
"CollectionID": "bafyreifilnntrughum4p63ntvocxvwqg2eveymltpziwk7lluvncjftula"
},
"Typ": 0,
"RelationName": "book_person",
"IsPrimary": true,
"DefaultValue": null,
"Size": 0
},
{
"FieldID": "bafyreibxx5wzp4iagt3jifid2r7hfzvbtzp2fuq26vku6t6ptk3ppwgxl4",
"Name": "plot",
"Kind": 11,
"Typ": 1,
"RelationName": null,
"IsPrimary": false,
"DefaultValue": null,
"Size": 0
},
{
"FieldID": "bafyreibbxpehr5radbbkkmsau5uuscoif4dxu6j3ef4by6f445fyx7pl3y",
"Name": "rating",
"Kind": 6,
"Typ": 1,
"RelationName": null,
"IsPrimary": false,
"DefaultValue": null,
"Size": 0
},
{
"FieldID": "bafyreihfb2izf5akjuua5jkijrgsgievsspboopupjq2its25owgle5pzm",
"Name": "title",
"Kind": 11,
"Typ": 1,
"RelationName": null,
"IsPrimary": false,
"DefaultValue": null,
"Size": 0
}
],
"Indexes": [],
"EncryptedIndexes": [],
"Policy": null,
"IsActive": true,
"IsMaterialized": true,
"IsBranchable": false,
"IsEmbeddedOnly": false,
"IsPlaceholder": false,
"VectorEmbeddings": []
}
]

Delete collections

To delete a collection, you need to truncate it (i.e. delete all its documents) and patch it for deletion.

Use the CLI commands defradb client collection truncate and defradb client collection patch.

For example, to delete the collection Book:

defradb client collection truncate --collection-id bafyreihqndwux4ewnlvmtcfvptikfvzu76tri2i5x4nbpiqh3hskxmagcm
defradb client collection patch '[{"op": "remove", "path": "/Book"}]'