I'm using #Schema({ timestamps: true }) to add createdAt & updatedAt to my records and returning these with the response. But seems the OpenAPI spec getting generated by the NestJs's Swagger plugin is not adding the createdAt or updatedAt. How can I get these two added to the generated OpenAPI spec.
openapi: 3.0.0
paths:
/participants/{participantId}:
get:
operationId: ParticipantController_findOne
parameters:
- name: participantId
required: true
in: path
schema:
type: string
responses:
'200':
description: The participant
content:
application/json:
schema:
$ref: '#/components/schemas/Participant'
components:
schemas:
Participant:
type: object
properties:
name:
type: string
description:
type: string
participantId:
type: string
required:
- name
- description
- participantId
My controller looks like this
#ApiOkResponse({
description: 'Get a participant',
type: Participant,
})
#Get(':participantId')
findOne(
#Param('participantId') participantId: string,
): Promise <Participant> {
return this.participantService.findOne(participantId);
}
My Mongoose schema looks like this,
#Schema({ timestamps: true })
export class Participant {
#Prop()
#ApiProperty()
participantId: string;
#Prop()
#ApiProperty()
name: string;
#Prop()
#ApiProperty()
description: string;
}
export const ParticipantSchema = SchemaFactory.createForClass(Participant);
My response looks like this,
{
"name": "Participant One",
"description": "The particicpant one",
"participantId": "participant-001",
"createdAt": "2022-10-14T20:00:52.778Z", // Added automatically by the `timestamps: true`
"updatedAt": "2022-10-14T20:04:31.081Z",// Added automatically by the `timestamps: true`
}
Related
I want to add an element to the array of all collections in the city collection, but Mongo creates the ID as duplicate.
this is my code
await this.cityRepository.updateMany(
{},
{
$push: {
tags: {
title: tagValue.title,
description: tagValue.description,
applyToAllCity: tagValue.cityId ? false : true,
},
},
},
);
City Schema
export class BaseCity extends Document {
#Prop({
type: String,
required: true,
})
_id: string;
#Prop({ type: String, unique: true })
code: string;
#Prop({ type: String, ref: Province.name })
province: string | Province;
#Prop({ type: String })
faName: string;
}
#Schema({ timestamps: true })
#Schema({ collection: 'city', virtuals: true, _id: false, timestamps: true })
export class City extends BaseCity {
#Prop({ type: String })
imageName: string;
#Prop({ index: true, type: String })
enName: string;
#Prop({ type: Number })
displayOrder: number;
#Prop({ type: Boolean })
isFeatured: boolean;
#Prop({ type: Boolean })
isEnabled: boolean;
#Prop({ type: Coordinate })
coordinate: Coordinate;
#Prop([{ type: Region, ref: Region.name, default: [] }])
region: Region[];
#Prop([{ type: SubMenu }])
subMenu: SubMenu[];
#Prop([{ type: CityTags }])
tags: CityTags[];
}
const CitySchema = SchemaFactory.createForClass(City);
CitySchema.index({ faName: 'text' });
export { CitySchema };
DB
As you can see, ID 63ec8f47efbd82c8face341a is duplicated in all documents.
Is there a solution to solve this problem?
To avoid duplicate IDs, you could use the $addToSet instead of $push. The $addToSet adds an element to an array only if it does not already exist in the set.
Check this:
await this.cityRepository.updateMany(
{},
{
$addToSet: {
tags: {
title: tagValue.title,
description: tagValue.description,
applyToAllCity: tagValue.cityId ? false : true,
},
},
},
);
Update:
To keep unique ids
await this.cityRepository.updateMany(
{},
{
$push: {
tags: {
_id: new ObjectId(),
title: tagValue.title,
description: tagValue.description,
applyToAllCity: tagValue.cityId ? false : true,
},
},
},
);
This is the fist time I use MongoDB with Mongoose and Typescript. I am defining an interface for each model of my database.
Should I add the _id field to the interfaces I create, like I am doing in this code snippet?
import mongoose, { Model, Document, ObjectId } from "mongoose";
export interface IUser extends Document {
_id: ObjectId;
name: string;
email: string;
password: string;
created: Date;
isPremium: boolean;
img?: string;
applicantProfile?: string;
businessProfile?: string;
}
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
isPremium: { type: Boolean, required: true, default: true },
created: { type: Date, required: true, default: Date.now },
img: String,
applicantProfile: String,
businessProfile: String,
});
export const User: Model<IUser> = mongoose.model("User", userSchema)
The tutorials I have read about Mongo + Typescript don't do this, but I have found that, if I don't declare the _id field in my interface, then, when I try to access the _id field, it has a value of any, which I don't like.
I'd like to know how you create the interfaces of your models and whether adding the _id field to the interface is a good practice.
I'm using mongoose with typescript and today I stepped into some confusion with Model and Document.
Here is definition of my subdocument.
export interface IUserUnitResource {
serialNumber: string;
role: string;
name?: string;
alarms: IUserAlarmResource[];
}
export interface IUserUnitEntity extends IUserUnitResource, mongoose.Document {
alarms: mongoose.Types.DocumentArray<IUserAlarmEntity>;
}
export const userUnitSchema = new mongoose.Schema(
{
serialNumber: { type: String, required: true, index: true },
role: { type: String, default: 'user' },
name: String,
alarms: { type: [userAlarmSchema], default: [] },
},
{ _id: false }
);
In mongoose documentation they say:
An instance of a model is called a document.
So I assumed that i can call ownerDocument method on that subdocument. But typescript gives me an error:
Property 'ownerDocument' does not exist on type 'IUserUnitEntity'.
But if i try to call that method using any i get desired document.
(uu as any).ownerDocument()
Do I have the typings wrong, or it's a bug?
some-dto.ts
export class CreateCatDto {
#ApiProperty()
name: string;
#ApiProperty()
age: number;
#ApiProperty()
breed: string;
}
I don't want response something like this:
#ApiOkResponse(
description: 'Cat object',
type: CreateCatDto
)
but my response must be array of like dto objects.
I want smth like soo
ApiOkResponse(
description: 'The record has been successfully removed.',
schema: {
type: 'array',
properties: {
obj: {
type: CreateCatDto
}
}
}
)
have you tried something like this:
#ApiOkResponse(
description: 'Cat object',
type: CreateCatDto,
isArray: true // <= diff is here
)
Let me know if it helps
I found another solution we can wrap in array like this
#ApiOkResponse(
description: 'Cat object',
type: [CreateCatDto]
)
And if you need to deal with multiple types :
#ApiOkResponse({
description: 'More or less dangerous animals',
schema: {
type: 'array',
items: {
oneOf: [
{ $ref: getSchemaPath(CreateCatDto) },
{ $ref: getSchemaPath(CreateAlligatorDto) }
],
},
},
})
I used the following code for my mongoose TypeScript model.
import mongoose = require('mongoose')
export interface PieceInterface extends mongoose.Document {
date: Date
summary: string
source: string
link: string
}
export const PieceSchema = new mongoose.Schema({
date: { type: Date, default: new Date(), required: true },
summary: { type: String, default: 'summary', required: true },
source: { type: String, default: 'source', required: true },
link: { type: String, default: '#', required: true }
})
export const Piece = mongoose.model<PieceInterface>('Piece', PieceSchema)
Now, when I use Piece.find({}).then(x => {...}), x is a Promise<PieceInterface[]> as expected.
However, I am not able to get
Piece.find({}).then(x => {
console.log(x[0].id)
})
to compile properly, it always tells me error TS2339: Property 'id' does not exist on type 'PieceInterface'.
Since, PieceInterface extends mongoose.Document, I looked...
interface Document extends MongooseDocument, NodeJS.EventEmitter, ModelProperties
And then,
class MongooseDocument implements MongooseDocumentOptionals
And finally this,
interface MongooseDocumentOptionals {
id?: string;
}
And in my mind, it should work. I am able to use variables provided by MongooseDocument and ModelProperties, but not MongooseDocumentOptionals.
Anything I'm missing?
References: mongoose.d.ts from GitHub
Definition of document
Definition of MongooseDocument
Definition of MongooseDocumentOptionals
Default field name for the ID in Mongo is _id not id, so you should do:
Piece.find({}).then(x => {
console.log(x[0]._id)
})
my friend,
Use this mechanism,
import mongoose = require('mongoose')
export interface PieceInterface extends mongoose.Document {
id : mongoose.Types.ObjectId //Add this line
date: Date
summary: string
source: string
link: string
}
export const PieceSchema = new mongoose.Schema({
date: { type: Date, default: new Date(), required: true },
summary: { type: String, default: 'summary', required: true },
source: { type: String, default: 'source', required: true },
link: { type: String, default: '#', required: true }
})
export const Piece = mongoose.model<PieceInterface>('Piece', PieceSchema)