mongodbmongoosenestjstypegoose

Typegoose is not saving array subdocuments properly in Nest.js app


I'm attempting to save an array of TaskOutcome subdocuments in my Task model, following the typegoose documentation:

import { prop } from '@typegoose/typegoose';

class TaskOutcome {
   @prop({ required: true }) public inputId: string;
   @prop() public label?: string;
   @prop() public value?: string;
}

export class Task {
   @prop() public _id: string;
   ...
   @prop({ _id: false, type: () => [TaskOutcome] })
   public outcomes: TaskOutcome[];
}
@Injectable()
export class TaskService {

   constructor(
      @InjectModel(Task) private readonly model: ReturnModelType<typeof Task>,
   ) {}

   public async saveTask(data: TaskDTO) {
      console.log(data.outcomes);
      const options: QueryOptions = { upsert: true, new: true };
      const result = await this.model.findByIdAndUpdate(data.id, data, options);
      console.log(result.outcomes);
   }
}

When I save a task document, all its props are saved as expected, except the outcomes array subdocuments. Instead, all I get is an array of empty objects. So even though the first console.log above shows me the correct input data, the second console.log gives me [{},{},{}] (confirmed when inspecting the database).

Anything obvious I'm doing wrong?

I'm using @nestjs/core@8.2.4, @typegoose/typegoose@9.3.1, nestjs-typegoose@7.1.38, and mongoose@6.1.2


Solution

  • Arrggghh. Ignore me. The code above is working perfectly fine.

    Instead there seems to be a bug with the Nest.js ValidationPipe, which was very subtly mangling my incoming TaskDTO data - so my outcomes array looked fine at a glance in the console, but was actually an array of arrays, instead of an array of objects.

    So typegoose was rightly ignoring it. If anyone stumbles on to this question, check the data you are saving really is exactly what it should be