今天我們要進行的是設計 報告(Report) 的資料模型與資料庫結構。接下來的部分會介紹 schemas
,特別針對 CHP555 報告的資料結構。因為將來可能會有其他類型的報告,我們會將這些報告模型分開管理。
資料夾 /reports/schemas
中,我們會建立一個名為 CHP555Report 的模型。將來若有其他類型的報告,它們也可以被放在同一個結構下,保持清晰且擴展性佳。
首先,我們會在 schemas
資料夾下建立 chp555Report.schema.ts
。這裡將會定義報告的核心結構,也就是報表上的欄位與對應的資料類型。
parties
欄位在設計報表時,會有多個參與者,像是目擊者或相關人員。每個參與者會有獨立的資料表來存儲具體的資訊。通過下方的設計,我們在報告模型中引用了參與者的 ID,確保資料之間的關聯性。
@Prop([{ type: SchemaTypes.ObjectId, ref: 'Party' }])
parties: Types.ObjectId[];
這段程式碼定義了 parties
欄位,它會連接到另一個 Party
模型,使用 ObjectId
類型來建立資料庫中的關聯。
接下來是 Chp555Report
的完整模型設計。這個模型包含了報告中所有關鍵的欄位,並根據需求指定了每個欄位的類型與是否必填。
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { Document, SchemaTypes, Types } from 'mongoose';
import {
SpecialConditionEnum,
NunmberEunm,
} from '../../../const/eumns/chp555Report';
import { Location } from './location.schema';
@Schema({ timestamps: true, minimize: false })
export class Chp555Report extends Document {
@Prop({ required: true })
userId: string;
@Prop({ required: true })
username: string;
@Prop({ required: false, enum: SpecialConditionEnum, type: Array })
specialConditions: SpecialConditionEnum[];
// 受傷人數
@Prop({ required: false, enum: NunmberEunm, type: String })
numberInjured: NunmberEunm;
// 死亡人數
@Prop({ required: false, enum: NunmberEunm, type: String })
numberKilled: NunmberEunm;
// 肇事逃逸
@Prop()
isFelony: boolean;
// 輕罪
@Prop()
isMisdemeanor: boolean;
@Prop()
city: string;
@Prop()
judicialDistrict: string;
@Prop()
county: string;
@Prop()
reportingDistrict: string;
@Prop()
beat: string;
// 星期幾
@Prop()
dayOfWeek: string;
// 違規停車
@Prop()
isTwoWay: boolean;
// 報告號碼
@Prop({ required: false })
reportNumber: string;
@Prop([{ type: SchemaTypes.ObjectId, ref: 'Party' }])
partyies: Types.ObjectId[];
@Prop(Location)
location: Location;
}
const Chp555ReportSchema = SchemaFactory.createForClass(Chp555Report);
Chp555ReportSchema.set('toJSON', {
virtuals: true,
versionKey: false,
transform: (doc, ret) => {
ret.id = ret._id;
delete ret._id;
return ret;
},
});
export { Chp555ReportSchema };
location
外鍵報告中另一個重要部分是事件的發生地點。我們將這些地點資訊設計成獨立的 Location
模型,並在主模型中引用。
...
import { Location } from './location.schema';
@Schema({ timestamps: true, minimize: false })
export class Chp555Report extends Document {
....
@Prop(Location)
location: Location;
}
...
詳細程式碼如下:
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema()
export class Location {
@Prop()
crashOccurredOn: string;
// GPS座標
@Prop({
type: {
latitude: { type: String },
longitude: { type: String },
},
})
gpsCoordinates: {
latitude: string;
longitude: string;
};
@Prop()
date: Date;
@Prop()
time: number;
@Prop()
stateHwyReel: boolean;
@Prop()
NCIC: string;
@Prop()
officerId: string;
@Prop()
photographsBy: string;
}
export const LocationSchema = SchemaFactory.createForClass(Location);
[!TIP] 回傳
下面程式碼可以讓回傳的 _id 變成 idChp555ReportSchema.set('toJSON', { virtuals: true, versionKey: false, transform: (doc, ret) => { ret.id = ret._id; delete ret._id; return ret; }, });
Party
參與者 模型除了報告的核心資訊之外,參與者(如駕駛、目擊者等)也是報告的重要組成部分。接下來我們來看 Party
模型的設計,這個模型儲存了參與者的身份、角色以及相關細節。
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { Document, SchemaTypes, Types } from 'mongoose';
import { Role } from '../../../../const/eumns/chp555Report';
import { DriverLicense } from './driverLicense.schema';
@Schema({ timestamps: true, minimize: false })
export class Party extends Document {
// 連結報告id
@Prop({ type: SchemaTypes.ObjectId, ref: 'Chp555Report' })
reportId: Types.ObjectId;
// 順序 , 必填
@Prop({ required: true })
order: number;
@Prop({ required: true })
name: string;
// 角色
@Prop({ type: String, enum: Role })
role: Role;
@Prop(DriverLicense)
driverLicense: DriverLicense;
toJSON() {
const obj = this.toObject();
obj.id = obj._id;
delete obj._id;
delete obj.__v;
return obj;
}
}
export const PartySchema = SchemaFactory.createForClass(Party);
driverLicense
駕駛的詳細資料存儲於 driverLicense
模型中,這裡包含了駕照號碼、車輛資訊等。該模型可以和 Party
參與者模型進行關聯,將駕駛的資料以結構化的方式儲存。
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema()
export class DriverLicense {
@Prop({})
licenseNumber: string;
// 角色選擇
@Prop({})
driver: boolean;
@Prop({})
ped: boolean;
@Prop({})
parkedVehCheckBox: boolean;
@Prop({})
bicycleCheckBox: boolean;
@Prop({})
otherCheckBox: boolean;
@Prop({})
operatorCheckBox: boolean;
@Prop({})
state: string;
@Prop({})
class: string;
@Prop({})
airBag: string;
@Prop({})
safetyEquipment: string;
@Prop({})
name: string;
@Prop({})
streetAddress: string;
@Prop({})
citystatezip: string;
@Prop({})
zip: string;
@Prop({})
sex: string;
@Prop({})
hair: string;
@Prop({})
eyes: string;
@Prop({})
weight: number;
@Prop({})
height: number;
@Prop({})
birthdate: string;
@Prop({})
race: number;
@Prop({})
homePhoneAreaCode: string;
@Prop({})
homePhone: string;
@Prop({})
businessPhone: string;
@Prop({})
businessPhoneAreaCode: string;
@Prop({})
insuranceCarrier: string;
@Prop({})
policyNumber: string;
@Prop({})
streetOrHwy: string;
@Prop({})
lane: string;
@Prop({})
thruLanes: string;
@Prop({})
totalLanes: string;
@Prop({})
speedLimit: string;
@Prop({})
licensePhotoUrl: string;
}
export const DriverLicenseSchema = SchemaFactory.createForClass(DriverLicense);
vehicel.schema.ts
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
import { Document, SchemaTypes, Types } from 'mongoose';
@Schema({ timestamps: true, minimize: false })
export class Vehicel extends Document {
@Prop({ required: true })
userId: string;
@Prop({ required: true })
username: string;
@Prop({ required: false })
reportNumber: string;
@Prop({ required: false })
vehicleNumber: string;
@Prop({ required: false })
vehicleType: string;
@Prop({ required: false })
vehicleYear: string;
@Prop({ required: false })
vehicleMake: string;
@Prop({ required: false })
vehicleModel: string;
@Prop({ required: false })
vehicleColor: string;
@Prop({ required: false })
vehicleLicensePlate: string;
@Prop({ required: false })
vehicleLicenseState: string;
@Prop({ required: false })
vehicleVIN: string;
@Prop({ required: false })
vehicleRegistrationExpiration: string;
@Prop({ required: false })
vehicleInsuranceCompany: string;
@Prop({ required: false })
vehicleInsurancePolicyNumber: string;
@Prop({ required: false })
vehicleInsuranceExpiration: string;
@Prop({ required: false })
vehicleInsuranceAgent: string;
@Prop({ required: false })
vehicleInsuranceAgentPhone: string;
@Prop({ required: false })
vehicleInsuranceAgentEmail: string;
@Prop({ required: false })
vehicleInsuranceAgentFax: string;
@Prop({ required: false })
vehicleInsuranceAgentAddress: string;
@Prop({ required: false })
vehicleInsuranceAgentCity: string;
@Prop({ required: false })
vehicleInsuranceAgentState: string;
@Prop({ required: false })
vehicleInsuranceAgentZip: string;
@Prop({ required: false })
vehicleInsuranceAgentCountry: string;
@Prop({ required: false })
vehicleInsuranceAgentLicense: string;
@Prop({ required: false })
vehicleInsuranceAgentLicenseState: string;
@Prop({ required: false })
vehicleInsuranceAgentLicenseExpiration: string;
@Prop({ required: false })
vehicleInsuranceAgentLicensePhone: string;
@Prop({ required: false })
vehicleInsuranceAgentLicenseEmail: string;
@Prop({ required: false })
vehicleInsuranceAgentLicenseFax: string;
@Prop({ required: false })
vehicleInsuranceAgentLicenseAddress: string;
@Prop({ required: false })
vehicleInsuranceAgentLicenseCity: string;
}
/src
├── /auth
├── /const
├── /reports
│ ├── chp555Report.controller.ts
│ ├── /schemas
│ │ ├── CHP555Report
│ │ │ ├── chp555Report.schema.ts
│ │ │ ├── location.schema.ts
│ │ │ └── /Party
│ │ │ ├── party.schema.ts
│ │ │ ├── driverLicense.schema.ts
│ │ │ └── vehicel.schema.ts
├── /service
│ └── chp555Report.service.ts
今天我們介紹了報告系統的資料庫模型與結構,未來這些資料會被應用於 CRUD 操作。下一篇文章,我們會展示如何基於這些模型進行 CRUD 操作,從建立到更新再到刪除資料,敬請期待!
#it鐵人