Data required to create a schema
Schema completed when data is created
Lightweight schema and class-based form used when multiple data is queried
Class-based complete form of data
Statistical data that can be extracted when data is queried
Statistical data extracted periodically when data is monitored
Data that defines the method of querying and the query statement in advance
Sort key-sort value used when data is sorted
Importance of Schema Structure
1
2@Model.Input('DroneInput')
3export class DroneInput {
4 @Field.Prop(() => String) // String, Int, Boolean, Float, JSON...
5 name: string;
6
7 @Field.Prop(() => String, { default: 'ws://10.10.150.10:9091' })
8 wsUri: string;
9}
1new this.Drone({'{ name: "myDrone", wsUri: "ws://10.10.150.10:9091" }'});
1this.createDrone({'{ name: "myDrone", wsUri: "ws://10.10.150.10:9091" }'});
1fetch.createDrone({'{ name: "myDrone", wsUri: "ws://10.10.150.10:9091" }'});
2fetch.updateDrone("droneId",{'{ name: "myDrone", wsUri: "ws://10.10.150.10:9091" }'});
1
2// Template.ts
3st.do.setNameOnDrone("myDrone"); // set state of form for create or update
4const droneForm = st.use.droneForm(); // droneForm.name
5
6// Util.ts
7const drone = st.use.drone(); // drone.name
8
1
2export const droneStatuses = ['active', 'offline', 'inactive'] as const;
3
4export type DroneStatus = (typeof droneStatuses)[number];
5
6@Model.Object('DroneObject')
7export class DroneObject extends BaseModel(DroneInput) {
8 @Field.Prop(() => String, { enum: droneStatuses, default: 'offline' })
9 status: DroneStatus;
10}
11
1const drone = await this.Drone.pickById("droneId"); // drone.status
1const drone = await this.getDrone("droneId"); // drone.status
1const drone = await fetch.drone("droneId"); // drone.status
1const drone = st.use.drone(); // drone.status
Performance Optimization Benefits
1@Model.Light('LightDrone')
2export class LightDrone extends Light(DroneObject, [
3 'name',
4 'status',
5] as const) {
6 isConnected() {
7 return this.status !== 'offline';
8 }
9}
1const droneList = await fetch.droneList({'{ status: "active" }'});
2// drone.name is possible, but drone.wsUri is not possible
1const droneMap = st.use.droneMap(); // Map<string, LightDrone>
1@Model.Full('Drone')
2export class Drone extends Full(DroneObject, LightDrone) {
3 static isDronesAllConnected(droneList: LightDrone[]) {
4 return droneList.every((drone) => drone.isConnected());
5 }
6 isAvailable() {
7 return this.isConnected() && this.wsUri.startsWith("ws://");
8 }
9}
1const drone = await fetch.drone("droneId"); // drone.isAvailable()
1const droneMap = st.use.droneMap(); // Map<string, LightDrone>
2const droneList = [...droneMap.values()];
3const isAllConnected = cnst.Drone.isDroneAllConnected(droneList);
1
2@Model.Insight('DroneInsight')
3export class DroneInsight {
4 @Field.Prop(() => Int, {"{ default: 0, accumulate: { $sum: 1 } }"})
5 count: number;
6}
1const droneInsight = await this.insight({"{ ...query }"}); // droneInsight.count
1const droneInsight = await fetch.droneInsight({"{ ...query }"}); // droneInsight.count
1const drone = st.use.droneInsight(); // droneInsight.count
1export const droneQuery = {"{
2 ...baseQueries,
3 byName: (name: string) => ({"{ name }"}),
4}
1const drone = await this.findByName("myDrone"); // db.Drone | null
2const drone = await this.findIdByName("myDrone"); // string | null
3const drone = await this.pickByName("myDrone"); // db.Drone
4const drone = await this.pickIdByName("myDrone"); // string
5const drones = await this.listByName("myDrone"); // db.Drone[]
6const droneIds = await this.listByName("myDrone"); // string[]
7const droneCount = await this.countByName("myDrone"); // number
8const droneExists = await this.existsByName("myDrone"); // string | null
9const droneInsight = await this.insightByName("myDrone"); // db.DroneInsight
1const drone = await this.findByName("myDrone"); // db.Drone | null
2const drone = await this.findIdByName("myDrone"); // string | null
3const drone = await this.pickByName("myDrone"); // db.Drone
4const drone = await this.pickIdByName("myDrone"); // string
5const drones = await this.listByName("myDrone"); // db.Drone[]
6const droneIds = await this.listByName("myDrone"); // string[]
7const droneCount = await this.countByName("myDrone"); // number
8const droneExists = await this.existsByName("myDrone"); // string | null
9const droneInsight = await this.insightByName("myDrone"); // db.DroneInsight
1export const droneSort = {"{
2 ...baseSorts,
3 alphabetical: {"{ name: 1 }"},
4}
1const drone = await this.findByName("myDrone", { sort: "alphabetical" });
2const drone = await this.findIdByName("myDrone", { sort: "alphabetical" });
3const drone = await this.pickByName("myDrone", { sort: "alphabetical" });
4const drone = await this.pickIdByName("myDrone", { sort: "alphabetical" });
5const drones = await this.listByName("myDrone", { sort: "alphabetical" });
6const droneIds = await this.listByName("myDrone", { sort: "alphabetical" });
1const drone = await this.findByName("myDrone", { sort: "alphabetical" });
2const drone = await this.findIdByName("myDrone", { sort: "alphabetical" });
3const drone = await this.pickByName("myDrone", { sort: "alphabetical" });
4const drone = await this.pickIdByName("myDrone", { sort: "alphabetical" });
5const drones = await this.listByName("myDrone", { sort: "alphabetical" });
6const droneIds = await this.listByName("myDrone", { sort: "alphabetical" });
1@Model.Scalar('DronePhysicalState')
2export class DronePhysicalState {
3 @Field.Prop(() => [Float], { default: [0, 0, 0] })
4 rpy: [number, number, number];
5
6 @Field.Prop(() => [Float], { default: [0, 0, 0] })
7 position: [number, number, number];
8
9 @Field.Prop(() => [Float], { default: [0, 0, 0] })
10 velocity: [number, number, number];
11}
1import { DronePhysicalState } from '../_lfg/lfg.constant';
2
3// ... //
4
5@Model.Object('DroneObject')
6export class DroneObject extends BaseModel(DroneInput) {
7 @Field.Prop(() => DronePhysicalState)
8 physicalState: DronePhysicalState;
9}
1@Model.Input('MissionInput')
2export class MissionInput {
3 @Field.Prop(() => ID, {"{ ref: 'drone' }"})
4 drone: string;
5}
1import { LightMission } from '../mission/mission.constant';
2
3// ... //
4
5@Model.Object('DroneObject')
6export class DroneObject extends BaseModel(DroneInput) {
7 @Field.Prop(() => LightMission, { nullable: true })
8 mission: LightMission | null;
9}
1import {"{ LightMission }"} from "../cnst_";
1import {"{ LightMission }"} from "../mission/mission.constant";
Option | Type | Default | Description | Example |
---|---|---|---|---|
nullable | boolean | false | Field value required, if nullable: true, data can be saved even if it is not present |
|
ref | string | - | Option for reference ID field, can specify reference collection name(e.g. drone) |
|
refPath | string | - | Option for reference ID field, if reference collection is variable, can specify reference collection name by referring to other field values |
|
default | any | - | Default value set when no value is entered, must be set for all fields except Model.Input |
|
type | email | password | url | - | Preset setting, default validation or example value is set |
|
immutable | boolean | false | Option that cannot be changed after document creation, after creation, changes to the field are not possible |
|
min | number | - | If the field's model is Int or Float, the minimum value can be limited in the save step |
|
max | number | - | If the field's model is Int or Float, the maximum value can be limited in the save step |
|
enum | any[] | - | If the field is enum, the const array can be specified to limit values other than the save step |
|
minlength | number | - | If the field's model is String, the minimum length of the string can be limited |
|
maxlength | number | - | If the field's model is String, the maximum length of the string can be limited |
|
query | object | - | Used in Model.Summary fields, the value obtained by performing the query is saved as the field's value |
|
accumulate | object | - | Used in Model.Insight fields, the value calculated in the aggregation step is saved as the field's value |
|
example | any | - | Can set the value that appears as an example when creating API Docs |
|
of | any | - | If the field's model is Map, the key value of the Map is string, and the model specified by of is set as the value type of the schema |
|
validate | any(value, model) => boolean | - | Can check validation in the save step.(unstable) |
|
Field value required, if nullable: true, data can be saved even if it is not present
1@Field.Prop(()=> String, { default: "untitled" }) title: string;
Option for reference ID field, can specify reference collection name(e.g. drone)
1@Field.Prop(()=> ID, { ref: "drone" }) drone: string;
Option for reference ID field, if reference collection is variable, can specify reference collection name by referring to other field values
1@Field.Prop(()=> ID, { refPath: "rootType" }) root: string; @Field.Prop(()=> String, { enum: ["drone", "mission"] }) rootType: string;
Default value set when no value is entered, must be set for all fields except Model.Input
1@Field.Prop(()=> String, { default: "untitled" }) title: string;
Preset setting, default validation or example value is set
1@Field.Prop(()=> String, { type: "email" }) email: string;
Option that cannot be changed after document creation, after creation, changes to the field are not possible
1@Field.Prop(()=> ID, { immutable: true }) creator: string;
If the field's model is Int or Float, the minimum value can be limited in the save step
1@Field.Prop(()=> Int, { min: 0 }) progress: number;
If the field's model is Int or Float, the maximum value can be limited in the save step
1@Field.Prop(()=> Float, { min: 0, max: 1 }) ratio: number;
If the field is enum, the const array can be specified to limit values other than the save step
1@Field.Prop(()=> String, { enum: ["active", "inactive"] }) status: "active" | "inactive";
If the field's model is String, the minimum length of the string can be limited
1@Field.Prop(()=> String, { minlength: 2 }) name: string;
If the field's model is String, the maximum length of the string can be limited
1@Field.Prop(()=> String, { maxlength: 30 }) title: string;
Used in Model.Summary fields, the value obtained by performing the query is saved as the field's value
1@Field.Prop(() => Int, { min: 0, default: 0, query: { status: { $ne: 'inactive' } } }) totalDrone: number;
Used in Model.Insight fields, the value calculated in the aggregation step is saved as the field's value
1@Field.Prop(() => Int, { default: 0, accumulate: { $sum: 1 } }) count: number;
Can set the value that appears as an example when creating API Docs
1@Field.Prop(()=> String, { example: "contact@akanjs.com" }) email: string;
If the field's model is Map, the key value of the Map is string, and the model specified by of is set as the value type of the schema
1@Field.Prop(()=> Map, { of: Date }) readAts: Map<string, Dayjs>;
Can check validation in the save step.(unstable)
1@Field.Prop(()=> String, { validate: (value)=> value.includes("@") }) email: string;