Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

656
Vistas
How to check reference when inserting in MongoDB (typegraphql, typegoose)?

Let say I have a simple collection events created by TypeGraphql and Typegoose which stores objects like:

{ _id: ObjectId(...), name: 'SomeEvent', category: ObjectId('...') }

and corresponding type:

@ObjectType()
export class Event {
  @Field(() => ID)
  _id!: Types.ObjectId

  @prop({ ref: 'Category' })
  @Field(() => Category)
  category!: Ref<Category>

  @prop()
  @Field()
  name!: string
}

I have also collection categories which contains right now only _id and name.

Now I want to insert some Event to database. Is it possible to automatically check if categoryId provided in input exist in collection categories and if it does not, throw an error? Right now, event can be added with anything in category field and next when I try to get it by query it throws an error that category cannot be resolved because there is no category with this ID. I know, that I can check it manually during adding event but if I have more fields like that it will be problematic.

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

With the help of Martin Devillers answer I was able to write a validator to validate referenced documents using class-validator with typegoose.

This is my refdoc.validator.ts:

import { ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
import { Injectable } from "@nestjs/common";
import { getModelForClass } from "@typegoose/typegoose";


@ValidatorConstraint({ name: "RefDoc", async: true })
@Injectable()
export class RefDocValidator implements ValidatorConstraintInterface {

    async validate(refId: string, args: ValidationArguments) {
        const modelClass = args.constraints[0];
        return getModelForClass(modelClass).exists({ _id: refId })
    }

    defaultMessage(): string {
        return "Referenced Document not found!";
    }
}

Then I can apply it on the DTO or model with the @Validate-Decorator. The Argument I'm passing in is the typegoose model.

@Validate(RefDocValidator, [Costcenter])
costcenterId: string;

Seems to be working for me, I'm open for any improvements..

Edit: Even better with custom decorator, as Martin Devillers suggested:

refdoc.validator.ts

import { registerDecorator, ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface } from "class-validator";
import { Injectable } from "@nestjs/common";
import { getModelForClass } from "@typegoose/typegoose";


@ValidatorConstraint({ name: "RefDoc", async: true })
@Injectable()
export class RefDocValidator implements ValidatorConstraintInterface {

    async validate(refId: string, args: ValidationArguments) {
        const modelClass = args.constraints[0];
        return getModelForClass(modelClass).exists({ _id: refId })
    }

    defaultMessage(): string {
        return "Referenced Document not found!";
    }
}

export function RefDocExists(modelClass: any, validationOptions?: ValidationOptions) {
    return function (object: Object, propertyName: string) {
        registerDecorator({
            name: 'RefDocExists',
            target: object.constructor,
            propertyName: propertyName,
            constraints: [modelClass],
            options: validationOptions,
            validator: RefDocValidator,
        });
    };
}

Then you can use it on the DTO like:

@ApiProperty()
@IsNotEmpty()
//@Validate(RefDocValidator, [Costcenter]) old
@RefDocExists(Costcenter) //new
costcenterId: string;
over 4 years ago · Santiago Trujillo Denunciar

0

Out of the box, neither MongoDB nor mongoose nor typegoose offer any automated referential integrity checks.

At the database level, this feature doesn't exist (which is also one of the fundamental differences between a database like MongoDB and SQL Server/Oracle).

However, at the application level, you can achieve this behavior in various ways:

  1. Middleware. Mongoose middleware allows you add generalized behavior to your models. This is useful if you're inserting documents in your EventModel in various places in your codebase and don't want to repeat your validation logic. For example:
EventModel.path('category').validate(async (value, respond) => {
    const categoryExists = await CategoryModel.exists({ _id: value })
    respond(categoryExists)
})
  1. Mongoose plugins. A plugin like mongoose-id-validator allows you to add the above behavior to any type of document reference in all your schemas.
  2. Manually. Probably the least favorite option, but I'm mentioning it for completeness sake: with mongoose's Model.exists() you can achieve this with a one-liner like: const categoryExists = await CategoryModel.exists({ _id: event.category })

To reiterate: all the above options are stopgaps. It's always possible for someone to go directly in your database and break referential integrity anyway.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda