Search code examples
mongoosenestjsmongoose-populate

How to populate mongoose references in nestjs?


I define a Person and Story schemas :

    @Schema()
    export class Person extends Document {
      @Prop()
      name: string;
    }
    export const PersonSchema = SchemaFactory.createForClass(Person);
    
    
    @Schema()
    export class Story extends Document {
    
      @Prop()
      title: string;
    
      @Prop()
      author:  { type: MongooseSchema.Types.ObjectId , ref: 'Person' }
    
    }
    export const StorySchema = SchemaFactory.createForClass(Story);

In my service I implemented save and read functions:

        async saveStory(){
        const newPerson = new this.personModel();
        newPerson.name  = 'Ian Fleming';
        await newPerson.save();
        const newStory  = new this.storyModel();
        newStory.title = 'Casino Royale';
        newStory.author = newPerson._id;
        await newStory.save();
      }
    
      async readStory(){
        const stories = await this.storyModel.
            findOne({ title: 'Casino Royale' })
        console.log('stories ',stories);
      }

When I ran readStory() I get the following output:

     stories  {
      _id: 5f135150e46fa5256a3a1339,
      title: 'Casino Royale',
      author: 5f135150e46fa5256a3a1338,
      __v: 0
    }

When I add a populate('author') to my query then I get author as null:

     stories  {
      _id: 5f135150e46fa5256a3a1339,
      title: 'Casino Royale',
      author: null,
      __v: 0
    }

How do I populate the author field with the referenced Person document ?


Solution

  • After much reading and testing on mongoose references in nestjs. I think the accepted answer can be improved. I will show this in 2 steps. The first step is showing the declaration of MongooseSchema and including the comment of @illnr regarding the author property to use Types.ObjectId instead of MongooseSchema.Types.ObjectId.

    import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
    import { Document, Types, Schema as MongooseSchema } from 'mongoose';
    
    @Schema()
    export class Story extends Document {
    
      @Prop()
      title: string;
    
      @Prop({ type: MongooseSchema.Types.ObjectId , ref: 'Person' })
      author:  Types.ObjectId 
    
    }
    
    export const StorySchema = SchemaFactory.createForClass(Story);
    

    And as a second step, I think it improves readability to use the Person class as type for the author property, as shown here.

    import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
    import { Document, Types, Schema as MongooseSchema } from 'mongoose';
    import { Person } from './person.schema'
    
    @Schema()
    export class Story extends Document {
    
      @Prop()
      title: string;
    
      @Prop({ type: MongooseSchema.Types.ObjectId , ref: 'Person' })
      author:  Person
    
    }
    
    export const StorySchema = SchemaFactory.createForClass(Story);