Models
In Mongur
, models are created by extending Model
and using a decorator called model
on the class. All the fields that
will be saved in the database need to be decorated with the field
decorator.
A basic model
import {model, Model, field} from "mongur";
@model()
class User extends Model<User>() {
@field()
firstName!: string;
@field()
lastName!: string;
@field()
email!: string;
@field()
password?: string
}
Learn more about @model and @field.
Note the parentheses in ModelUser>()
. The base class is actually returned from a function call.
Embedded documents
A model can be embedded in another model in the same way as any other fields except that its type must be specified
in the @field
decorator using the type
property.
@field({type: Publisher})
If it's an array, the type needs to be specified as an array like this:
@field({type: [Author]})
Here's a complete example:
import {model, Model, field} from "mongur";
// An embedded document model
@model
class Publisher extends Model<Publisher> {
@field()
name?: string
@field()
logo?: string
}
// Another embedded document model
@model
class Author extends Model<Author>{
@field()
name?: string
@field()
photo?: string
}
// Main model
@model
class Book extends Model<Book>(){
@field()
title!: string;
@field()
price!: number;
@field({type: [Author]})
authors?: Author[]
@field({type: Publisher})
publisher?: Publisher
}
Sometimes, you may not want to have an _id
field with the sub documents. In that you can specify that in the @field
decorator.
@field({type: Publisher, _id: false})
publisher?: Publisher
See all the available options in @field.
Reference another model
Referencing another model is similar to how embedding a model works except that the typescript type of the
field need to be specified with Ref
. The type
property in @field
decorator needs to be specified too just like before.
import {model, Model, field, Ref} from "mongur";
@model
class BlogPost extends Model<BlogPost>(){
@field()
title!: string;
@field()
body!: string;
@field({type: User})
author!: Ref<User>;
}
Use a non-model class as the field type
You can create a custom type by extending Factory
and implementing 2 methods:
parse
import {field, model, Model, Factory} from "mongur";
// Our non-model class
export class LatLng {
constructor(public readonly lat: number, public readonly lng: number) {
}
}
// A factory class to transform the data to and from db and object
class LatLngFactory extends Factory<any, LatLng> {
// Parse value saved in the db, to the actual type
parse(input: any): LatLng {
return new LatLng(input["lat"], input["lng"])
}
// Covert object instance to the intended format to save in the db
value(input: LatLng): any {
return {
lat: input.lat,
lng: input.lat
}
}
}
// Actual model
@model()
export class City extends Model<City>() {
@field()
name!: string
@field({type: LatLngFactory})
center?: LatLng
}
Extending from a common base class
import {model, Model, field} from "mongur";
// Write your base class
class BaseModel {
@field()
createdAt!: Date;
@field()
updatedAt!: Date;
}
// Write the actual model
@model
class Post extends Model<Post & BaseModel>(BaseModel){
@field()
title!: string;
@field()
body!: string;
}
interface Post extends BaseModel {}
Here, Post & BaseModel
is for definition. BaseModel
next to it, in parentheses, actually does the work of extending.
Finally, interface User extends BaseModel {}
is also for type definition. This is the only weird thing about this library (Promise!).