Pre-1.0 hoardDB is pre-1.0. Expect breaking changes.

Data types

A field of a bucket is either a store (a queue, a stack, a map, a file store; see Store types) or a scalar: one value per document, such as a name, a count or a date. This page is the scalar types. You declare one when you create the bucket:

[h]oardDB [app]> create bucket Event { Title string, Seats int, Price decimal, Starts datetime, Ref uuid, Tags array, Venue object, Open bool }
OK  created bucket app.Event (8 fields)
Fields: Title string, Seats int, Price decimal, Starts datetime, Ref uuid, Tags array, Venue object, Open bool

Documents are stored as BSON, so the types are BSON’s. describe bucket Event lists each field with its type.

The types

TypeMeant to holdWrite it as
stringUTF-8 text"Launch"
int32a whole number that fits in 32 bits5, or {$numberInt: "5"}
inta whole number that fits in 64 bits120, or {$numberLong: "9007199254740993"}
doublea 64-bit floating point number1.5, or {$numberDouble: "2.5"}
decimalan exact decimal, for money{$numberDecimal: "19.99"}
numberany of the four numeric types aboveany of the forms above
booltrue or falsetrue
datetimea moment in time, to the millisecond{$date: "2026-12-01T18:30:00Z"}, or milliseconds since 1970: {$date: 1730628000000}
bsontimestampBSON’s internal timestamp: a count of seconds and an ordinal inside that second{$timestamp: {t: 1, i: 1}}
binaryraw bytes{$binary: {base64: "aGk=", subType: "00"}}
uuida 16-byte universally unique identifier{$uuid: "0192a3b4-c5d6-7890-abcd-ef1234567890"}
objectida 12-byte object id{$oid: "507f1f77bcf86cd799439011"}
objecta nested document{City: "Tirana", Room: 2}
arraya list of values of any type["talk", "free"]
regexa regular expression{$regularExpression: {pattern: "a", options: "i"}}
nullno valuenull
anyany of the types aboveany of the forms above

The forms in braces with a $ are Extended JSON: they are how a value that JSON has no word for is written. A date, a uuid, a decimal, an object id, bytes and a regular expression have no plain literal, so write them in these forms. A plain "2026-12-01T18:30:00Z" is a string, not a date.

A document reads back as you wrote it:

[h]oardDB [app]> db.Event.insert({_id_: "e1", Title: "Launch", Seats: 120, Price: {$numberDecimal: "19.99"}, Starts: {$date: "2026-12-01T18:30:00Z"}, Ref: {$uuid: "0192a3b4-c5d6-7890-abcd-ef1234567890"}, Tags: ["talk", "free"], Venue: {City: "Tirana", Room: 2}, Open: true})
OK  id=e1
[h]oardDB [app]> db.Event["e1"].get()
{"Open": true, "Price": {"$numberDecimal":"19.99"}, "Ref": {"$uuid":"0192a3b4-c5d6-7890-abcd-ef1234567890"}, "Seats": 120, "Starts": {"$date":"2026-12-01T18:30:00Z"}, "Tags": ["talk","free"], "Title": "Launch", "Venue": {"City":"Tirana","Room":2}, "_id_": "e1"}

Keys print in sorted order. A whole number above 9223372036854775807 is stored as a double, so it loses precision; write it as a string, or as a decimal, if you need every digit.

The type is recorded, not checked

Ring mode records a field’s type and prints it, but it does not check a written value against it. A field declared int will hold a string if you write one:

[h]oardDB [app]> db.Event.insert({_id_: "e2", Seats: "many"})
OK  id=e2
[h]oardDB [app]> db.Event["e2"].get()
{"Seats": "many", "_id_": "e2"}

Check a value in your own code before you write it, and do not rely on the declared type to keep a wrong one out. What the server does refuse is a field name the bucket does not declare, with the list of the names it does:

[h]oardDB [app]> db.Event.insert({_id_: "e3", Capacity: 10})
CLI error: bucket app.Event declares no field "Capacity". Its scalar fields are: Title string, Seats int, Price decimal, Starts datetime, Ref uuid, Tags array, Venue object, Open bool. Check the spelling; the document id is the id argument, not a field

Spelling

A type word is spelled exactly as in the table, in lower case. Other spellings are refused, and the refusal names the word to use:

[h]oardDB [app]> create bucket Z { A integer }
CLI error: PARSE_ERROR: "integer" is not a type word here: the catalog records one spelling, and it is "int" ('A int') (character 21). ...

integer and int64 are int, float is double, boolean is bool, and date and timestamp are datetime. A word that is not a type at all is refused with the full list. A field is declared once: naming it twice is refused.

Changing a type

A field’s type never changes. alter bucket adds a field or drops one (alter bucket Event { add Email string }). To change a type, add a field of the type you want, copy the values across, and drop the old field. Limitations has the rest of what ring mode does not do yet.

Not written the way you might expect

  • There is no now() and no ISODate(...) in ring mode: a statement that uses either is refused as “not a value”. Write the date as {$date: ...}.
  • _id_ is not a declared field. It is the document’s id and is always there; see Getting started.
  • A store is not a scalar. Photos lifoStore declares a stack that belongs to each document, and it holds elements, not a value: see Store types.

Source: docs/user/data-types.md in the repository.