Janik
Janik

Reputation: 121

Can't get mongoose virtual populate up and running in NestJS app

I am currently working on a project where virtual populates are quite necessary:

There's a customer scheme, a document scheme as well as some others referencing the customer. Inside the customer I want to populate the referenced items.

I already had a working Model using Typegoose, which I had to remove from the project because of late incompatibilities. This is how it worked before:

  @prop({ 
    ref: () => DMSDocument,
    foreignField: 'linkedCustomers', // compare this value to the local document populate is called on
    localField: '_id', // compare this to the foreign document's value defined in "foreignField",
    justOne: false
  })
  public documents: { type: Types.ObjectId, ref: 'DMSDocument' }[];

Now I was trying to achieve this using nestjs/mongoose only after removing typegoose:

@Prop({ 
    virtual: 'documents',
    ref: 'DMSDocument',
    foreignField: 'linkedCustomers',
    localField: '_id',
  })
  public documents: DMSDocument[];

Virtual getters working just fine since I'm just using

@Schema({ toJSON: { virtuals: true, getters: true }, toObject: { virtuals: true, getters: true }})

The model ist populated like this:

this.customerModel.findOne(params)
.populate('documents', '', 'DMSDocument')
.populate('repairs', '', 'Repair')

I am somehow stuck - I just get empty arrays, no errors. What Am I missing? Are they even possible using nestjs/mongoose?

Upvotes: 5

Views: 4769

Answers (2)

user10033434
user10033434

Reputation: 455

Answer for 2024

You can achieve this in Nest.js now (my version is: 10.0.0) by doing the following:

In your customer module:

imports: [
    MongooseModule.forFeatureAsync([{
      name: Customer.name,
      useFactory: () => {
        const schema = CustomerSchema;
        schema.virtual('documents', {
            ref: 'DMSDocument',
            localField: '_id',
            foreignField: 'links.customers',
            justOne: false
        });
        return schema;
      }
    }])
 ],

This is the link to the documentation: https://docs.nestjs.com/techniques/mongodb#hooks-middleware

You can also create virtuals directly in the schema like the following:

class Person {
  @Prop()
  firstName: string;

  @Prop()
  lastName: string;

  @Virtual({
    get: function (this: Person) {
      return `${this.firstName} ${this.lastName}`;
    },
  })
  fullName: string;
}

This is from the docs also. link: https://docs.nestjs.com/techniques/mongodb#virtuals

Upvotes: 0

Janik
Janik

Reputation: 121

Okay, I managed to get things working again, but not in a preferred way:

After defining the class and converting it to a schema via

export const CustomerSchema = SchemaFactory.createForClass(Customer);

I just had to "manually" add the virtual populates:

CustomerSchema.virtual('documents', {
  ref: 'DMSDocument',
  localField: '_id',
  foreignField: 'links.customers',
  justOne: false
}); 

Everything is working as expected, but I'd prefer a way using the decorators.

Upvotes: 3

Related Questions