Each collection can be thought of as an object to which properties can be
assigned. We call such an object a Thing. To access something in the collection, all you need to do,
is to start with a . (dot), followed by a function or property name. Another way to access
the collection is to use the collection’s Id. All things which are stored in
ThingsDB get an unique Id. Since the collection root is also a Thing, it has its own
id.
For example, to read the collection’s ID:
.id(); // This will return the collection ID
To store something inside the collection you only need to make sure the data is attached to the collection.
For example:
// Saves a number `42`
.number = 42;
// Saves some text to property `txt`
.txt = 'Hello ThingsDB!';
// Saves a new `thing` to property `card`
.card = {
suit: 'Spades',
value: 1,
};
// The last value will be the return value. It may be just `nil`
nil;
Reading data from a collection works similar. Just ask for the property.
For example:
.txt; // Returns the value of property `txt`
Result in JSON format:
"Hello ThingsDB!"
To return multiple properties at once, it is often useful to put them in an array:
[.txt, .number]; // Returns both property `txt` and `number`
And the result in JSON format:
[
"Hello ThingsDB!",
42
]
Stored things will get an Id (#) from ThingsDB.
For example look at our
cardexample:
.card; // Returns the value of property `card`
Result in JSON format (The Id (
#) might differ since it is auto-generated by ThingsDB)
{
"#": 17,
"suit": "Spades",
"value": 1
}
To ensure data integrity and consistent structure within a collection, you can enforce a type schema. This process involves defining a custom type and applying it to the collection’s root.
Every collection in ThingsDB starts as a single, basic thing. This “root” is an untyped thing that holds all your collection’s data.
To enforce structure, we must convert this untyped root into a structured, custom type.
First, you must define your new custom type. This example creates a type called Root, but you can choose any name relevant to your data model.
// Step A: Declare the new type structure
new_type('Root'); // Initially an empty type definition.
// Step B: Convert the collection's root to the defined type
.to_type('Root');
Once the .to_type('Root') command executes, your collection’s entire structure is governed by the Root type.
Because we initially defined Root as an empty type, this conversion effectively locks the collection to an empty object. Any subsequent attempt to add data to the collection must conform to additions made to the Root type.
To actually give your collection a structure (i.e., add properties), you use the mod_type function.
Suppose you want to give your collection a required name property that must be a string. You modify the Root type, and the change is automatically applied to your collection’s root object.
// Modify the 'Root' type:
// mod_type(Type, Action, PropertyName, PropertyType, InitialValue)
mod_type('Root', 'add', 'name', 'str', 'My Collection Name');
// The new property is immediately available on the collection root
.name; // Returns: "My Collection Name" (the initial value)
// Attempting to change the name to a non-string will result in an error
.name = 123; // ERROR: Must be a string
By typing the collection’s root, you ensure that all operations that modify the collection’s structure must pass through the type definition, providing a single, reliable source of schema validation for all components interacting with your data.
See the Collection API documentation for functions which can be used to manipulate ThingsDB data.