Properties
A property is a named value on an object, such as an invoice's number, status, or due date. Its schema determines which values Sixb accepts.
Define a property
Add prop(id, schema, options?) to an object type's properties array:
import { prop, stringEnum } from "@sixb/core/ontology"
prop("number", "string", { required: true })
prop("status", stringEnum(["draft", "sent", "paid"]))
IDs must be unique within the type. Use name for a separate display label and description
for additional context. Without a name, Sixb uses the ID.
Choose a schema
| Schema | Values |
|---|---|
"string", "uuid" | Text or a UUID string. |
"boolean" | true or false. |
"integer", "double" | Whole numbers or floating-point numbers. |
"decimal" | Exact decimal values, represented as strings. |
"date", "timestamp" | A calendar date or timestamp. Writes accept Date values or ISO strings. |
ref.file() | A reference to an uploaded file. The string "fileRef" is equivalent. |
ref.user() | A reference to a Sixb user, such as an assignee. |
stringEnum([...]), integerEnum([...]) | A fixed set of string or integer values. |
array, object, map | Structured values, shown below. |
valueTypeRef(ValueType) | A reusable schema. |
Scalar schemas are strings. Schemas that point somewhere else are built with ref: ref.file(),
ref.user(), and ref(ObjectType) for action parameters. To
point from one object to another, use a link instead; ref(ObjectType) on a property is
rejected.
For exact decimal values, use decimal() with a string rather than converting through a
JavaScript number:
import { decimal, prop } from "@sixb/core/ontology"
prop("amount", "decimal")
const amount = decimal("124.50")
Keep a separate currency property when an amount represents money. Physical units are for measurements such as temperature or pressure.
Required and nullable values
Properties are optional and non-nullable by default. required means a new object must include
the property. nullable allows an explicit null value. The two options are independent:
prop("number", "string", { required: true })
prop("note", "string", { nullable: true })
An omitted property and a property set to null are different values. Updating an existing
object can leave required properties unchanged; see Create or update an object.
The primary property is always a required string.
Structured values
Use arrays for lists, objects for named fields, and maps for dynamic keys:
prop("tags", { type: "array", items: "string" })
prop("address", {
type: "object",
properties: {
street: { schema: "string", required: true },
city: { schema: "string", required: true },
postcode: { schema: "string" },
},
})
prop("labels", { type: "map", keySchema: "string", valueSchema: "string" })
Nested fields can be required or nullable, and structured schemas can be nested. There is no
unrestricted json property schema; describe the shape you expect.
Use a value type when several properties share a shape. If the value needs its own identity or relationships, define an object type and connect it with a link.
Reference a user
Use ref.user() when a property names a member of your project, such as a task's assignee or a
request's reviewer:
import { prop, ref } from "@sixb/core/ontology"
prop("assignee", ref.user(), {
nullable: true,
query: { searchable: true, filterable: true, facet: true },
})
prop("reviewers", { type: "array", items: ref.user() })
The value is { type: "user", id }, with the ID of a Sixb user. A write can only set a user who
exists and is active. Values an object already holds stay valid: suspending a user does not
block later updates of objects that reference them. The reference carries no display data and
grants no access by itself.
Build a value with userRef(id). Queries can match a user with eq, neq, in, and exists,
find a user in an array with contains, and group objects by user with facet:
import { userRef } from "@sixb/core"
const assignee = userRef("usr_1")
await sixb.objects(Task).upsert({ properties: { id: "task-1", assignee } })
await sixb
.objects(Task)
.query()
.where((task) => task.or(task.p.assignee.eq(assignee), task.p.reviewers.contains(assignee)))
.list()
A signed-in Principal whose type is "user" is already a user reference. User references
cannot be sorted, searched as text, or listed in search.exact.
User references are set by your code, actions, and workflows. Projections, telemetry properties, link properties, and action parameters of a share cannot use them yet. For a person who is part of your domain rather than a project member, such as a customer contact, define an object type.
Enable queries
Add query options to the properties you filter, sort, search, or group. Set searchable: true
alongside the capabilities you need:
prop("status", stringEnum(["draft", "sent", "paid"]), {
query: { searchable: true, filterable: true, facet: true },
})
prop("dueDate", "date", {
query: { searchable: true, filterable: true, sortable: true },
})
| Option | Enables |
|---|---|
searchable | Required for all other query options. |
filterable | Property predicates such as equality, ranges, and existence. |
sortable | Ordering results by this property. |
text | Keyword search on a string or string enum. |
exact | Using this property in the type's exact-match search profile. |
facet | Grouped counts for scalar, enum, or user reference values, excluding file references. |
weight | Positive text-ranking weight; also requires text: true and provider support. |
Without query options, a property can still be stored and read. Comparing the primary ID with
eq or in does not need query options. See Querying for the calls these
settings enable.
Configure search
Set search.defaultText on the object type to choose which fields a plain search("...")
query uses. Enable text on those properties in the same definition:
// ontology/customer.ts
import { defineObjectType, prop } from "@sixb/core/ontology"
export const Customer = defineObjectType({
id: "Customer",
name: "Customer",
properties: [
prop("id", "string", { required: true, primary: true }),
prop("name", "string", {
required: true,
query: { searchable: true, text: true, sortable: true },
}),
],
search: {
title: "name",
defaultText: ["name"],
exact: ["id"],
},
})
title selects the string field used to label search results. exact lists exact-match fields;
each needs query.exact: true, except the primary ID. Search profiles use static properties.
Configure vector search
Use search.vectors to search by meaning. Each named profile combines static string or string-enum
properties with a registered embedding model:
// ontology/product.ts
import { defineObjectType, prop } from "@sixb/core/ontology"
import { productEmbedding } from "../lib/models"
export const Product = defineObjectType({
id: "Product",
name: "Product",
properties: [
prop("id", "string", { required: true, primary: true }),
prop("title", "string", { required: true }),
prop("description", "string"),
],
search: {
vectors: {
content: { source: ["title", "description"], model: productEmbedding },
},
},
})
The source properties need no query flags. Sixb stores embeddings separately from your object's properties. See Search by meaning for indexing and querying.
Record history
Properties use mode: "static" by default: they hold the object's current value. Use
mode: "telemetry" when you also need a timestamped history:
prop("progress", "integer", { mode: "telemetry" })
prop("online", "boolean", { mode: "telemetry" })
Telemetry supports scalar and structured values, but cannot contain file or user references. Values
with a physical semanticType also require a valid unit.
See Telemetry for appending readings and querying their history.
Protect sensitive values
Mark a property to hide its value from roles without the matching clearance:
prop("amount", "decimal", { markings: [financial] })
See Markings.