NestJs Nested Document In MongoDB
insert nested document in mongoose(Date field not work):
In Model:
@Schema()
export class ReceptionTime {
@Prop({type: Date})
startTime: Date;
@Prop({type: Date})
callTime: Date;
@Prop({type: Date})
endTime: Date;
}
export const receptionTimeObjectSchema=SchemaFactory.createForClass(ReceptionTime);
@Schema()
export class Reception {
@Prop({type: receptionTimeObjectSchema})
// @ValidateNested() @Type(() => ReceptionTime)
receptionTimes: ReceptionTime;
}
export const ReceptionSchema = SchemaFactory.createForClass(Reception);
In Dto:
export class ReceptionTime {
@IsOptional()
@IsDateString()
startTime: Date;
@IsOptional()
@IsDateString()
callTime: Date;
@IsOptional()
@IsDateString()
endTime: Date;
}
export class CreateReceptionDto {
@ValidateNested() @Type(() => ReceptionTime)
@IsOptional()
receptionTimes: ReceptionTime;
}
Example 2:
addressUser.schema.ts
import {Prop, Schema, SchemaFactory} from "@nestjs/mongoose";
import {AddressEnum} from "../../common/enums/general.enum";
@Schema()
export class AddressUser{
@Prop()
countryId:string;
@Prop()
provinceId:string;
@Prop()
cityId:string;
@Prop()
address:string;
@Prop()
postalCode:string;
@Prop({type:String,enum:AddressEnum})
type:string;
@Prop({default:Date()})
createdAt: Date;
@Prop({default:Date()})
updatedAt: Date;
}
export const addressUserObjectSchema = SchemaFactory.createForClass(AddressUser);
addressUserObjectSchema.pre('save', function (next) {
let addressUser = this as any;
const now = new Date();
if (!addressUser.createdAt) {
addressUser.createdAt = now;
}
addressUser.updatedAt = now;
next();
});
addressUser.type.ts
import {IsDateString, IsEnum, IsMongoId, IsNotEmpty, IsNumber, IsOptional, IsString} from "class-validator";
import {AddressEnum} from "../../common/enums/general.enum";
export class AddressUserType {
@IsOptional()
@IsMongoId()
countryId:string;
@IsOptional()
@IsMongoId()
provinceId:string;
@IsOptional()
@IsMongoId()
cityId:string;
@IsNotEmpty()
@IsString()
address:string;
@IsOptional()
@IsString()
postalCode:string;
@IsNotEmpty()
@IsEnum(AddressEnum)
type:string;
@IsOptional()
@IsDateString()
createdAt:string;
@IsOptional()
@IsDateString()
updatedAt:string;
}
user.model.ts
import {Prop, Schema, SchemaFactory} from '@nestjs/mongoose';
import {Document} from 'mongoose';
import * as bcrypt from 'bcrypt';
import {ActivationEnum, AddressEnum, GenderEnum, MaritalEnum} from "../../common/enums/general.enum";
import {MobileType} from "../types/mobile.type";
import {PhoneType} from "../types/phone.type";
import {ServiceType} from "../types/service.type";
import {SpouseType} from "../types/spouse.type";
import {AddressUser, addressUserObjectSchema} from "../schemas/addressUser.schema";
export type UserDocument = User & Document;
export class UserRes extends Document {
mobile:string;
}
@Schema()
export class User extends Document {
@Prop()
mobileCountryId: string;
@Prop()
mobile:string;
@Prop()
countryId: string;
@Prop({type:String,enum:GenderEnum})
gender: string;
@Prop()
firstName: string;
@Prop()
lastName: string;
@Prop()
fatherName: string;
@Prop()
username: string;
@Prop()
password: string;
@Prop()
nationalCode: string;
@Prop()
identityCode: string;
@Prop({type:String,enum:ActivationEnum})
status:string;
@Prop()
email: string;
@Prop()
roles: [string];
@Prop({type: MobileType})
mobiles:MobileType[];
@Prop({type: Number})
birthCertificateId: number;
@Prop()
dateOfBirth: Date;
@Prop({type: [addressUserObjectSchema]})
addresses: AddressUser[];
@Prop({type:PhoneType})
phones: PhoneType[];
@Prop({type:String,enum:MaritalEnum})
maritalStatus: string;
@Prop({type:SpouseType})
spouses: SpouseType[];
@Prop()
placeOfIssueCityId: string;
@Prop()
placeOfBirthCityId: string;
@Prop()
referralWayId: string;
@Prop()
referrerUserId: string;
@Prop()
referrerFullName: string;
@Prop()
referrerAddress: string;
@Prop({type:ServiceType})
services: ServiceType[];
@Prop()
createdAt: Date;
@Prop({required: false})
updatedAt: Date;
@Function()
checkPassword: Function;
@Function()
checkOldPassword: Function;
}
export const UserSchema = SchemaFactory.createForClass(User);
UserSchema.methods.checkPassword = async function (attempt, callback) {
let user = this;
bcrypt.compare(attempt, user.password, (err, isMatch) => {
if (err) return callback(err);
callback(null, isMatch);
});
};
UserSchema.methods.checkOldPassword = function (attempt, callback) {
let user = this;
// console.log('check model:',attempt)
// console.log('check model user password:',user.password)
bcrypt.compare(attempt, user.password, (err, isMatch) => {
if (err) return callback(err);
callback(null, isMatch);
});
};
UserSchema.pre('save', function (next) {
let user = this as any;
//UpdatedAt and CreatedAt
const now = new Date();
if (!user.createdAt) {
user.createdAt = now;
}
user.updatedAt = now;
//PASSWORD and ActivationCode
// Generate a salt and use it to hash the user's password
// user.password = Math.floor(Math.random() * (9999 - 1000)) + 1000;
// bcrypt.genSalt(10, (err, salt) => {
// if (err) return next(err);
// bcrypt.hash(user.password.toString(), salt, (err, hash) => {
// if (err) return next(err);
// user.password = hash;
// next();
// });
// });
next();
});
create-user.dto.ts
import {
IsString,
IsNotEmpty,
Length,
IsOptional,
isAlphanumeric,
IsAlphanumeric,
IsNumber,
Validate, IsArray, IsMongoId, IsEnum, IsEmail, ValidateNested, IsDate, IsDateString
} from 'class-validator';
import {ActivationEnum, GenderEnum, MaritalEnum} from "../../common/enums/general.enum";
import {Type} from 'class-transformer';
import {MobileType} from "../types/mobile.type";
import {AddressUserType} from "../types/addressUser.type";
import {PhoneType} from "../types/phone.type";
import {ServiceType} from "../types/service.type";
import {SpouseType} from "../types/spouse.type";
import {NationalCode} from "../decorators/NationalCode.decorators";
export class CreateUserDto {
@IsMongoId()
@IsNotEmpty()
mobileCountryId: string;
@IsString()
@IsNotEmpty()
@Length(11, 11)
mobile:string;
@IsMongoId()
@IsNotEmpty()
countryId: string;
@IsNotEmpty()
@IsEnum(GenderEnum)
gender: string;
@IsNotEmpty()
@IsString()
firstName: string;
@IsNotEmpty()
@IsString()
lastName: string;
@IsString()
@IsNotEmpty()
fatherName: string;
@IsString()
@IsOptional()
username: string;
@IsString()
@IsOptional()
@Length(6)
password: string;
@IsString()
@IsOptional()
@NationalCode({message:"NationalCod is Invalid"})
nationalCode: string;
@IsString()
@IsOptional()
@Length(8)
identityCode: string;
@IsEnum(ActivationEnum)
status:string;
@IsOptional()
@IsEmail()
email:string
@IsNotEmpty()
@IsArray()
roles: []
@IsArray()
@IsOptional()
@ValidateNested() @Type(() => MobileType)
mobiles:MobileType[];
@IsOptional()
@IsNumber()
birthCertificateId: number;
@IsDateString()
dateOfBirth: Date;
@IsOptional()
@IsOptional()
@ValidateNested() @Type(() => AddressUserType)
addresses: AddressUserType[];
@IsOptional()
@ValidateNested() @Type(() => PhoneType)
phones: PhoneType[];
@IsEnum(MaritalEnum)
maritalStatus: string;
@IsOptional()
@IsMongoId()
placeOfIssueCityId: string;
@IsOptional()
@IsMongoId()
placeOfBirthCityId: string;
@IsOptional()
@IsMongoId()
referralWayId: string;
@IsMongoId()
@IsOptional()
referrerUserId: string;
@IsOptional()
@IsString()
referrerFullName: string;
@IsOptional()
@IsString()
referrerAddress: string;
@IsOptional()
@ValidateNested() @Type(() => ServiceType)
services: ServiceType[];
@IsOptional()
@ValidateNested() @Type(() => SpouseType)
spouses: SpouseType[];
@IsOptional()
@IsString()
spouseCountryId: string;
@IsOptional()
@IsString()
spouseFirstName: string;
@IsOptional()
@IsString()
spouseLastName: string;
@IsOptional()
@IsString()
spouseFatherName: string;
@IsOptional()
@IsString()
spouseNationalCode: string;
@IsOptional()
@IsString()
spouseIdentityCode: string;
@IsOptional()
@IsDateString()
dateOfMarriage:Date;
@IsOptional()
@IsDateString()
spouseDateOfBirth:Date;
}