4

I am using nest js with mongodb and for the mongodb modelling i am using Typegoose . they did not have autopopulate functionality yet.

I am using

https://github.com/szokodiakos/typegoose

and just want to use auto populate

https://www.npmjs.com/package/mongoose-autopopulate

Akash Gupta
  • 389
  • 1
  • 4
  • 10
  • Please provide details on what have you tried and tested for achieving your above requirement. Probably then people in the community would be able to help you. – Sumit Surana Apr 10 '19 at 16:44
  • 1
    Manual populate is possible, as per post https://stackoverflow.com/a/51837725/2727080 – Miloš Stanić Apr 15 '19 at 22:53

5 Answers5

4

There is an autopopulate option for the prop decorator, which is used like so:

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

class Person {
  @prop()
  name: string
}

class User {
  @prop({ autopopulate: true, ref: Person })
  person: Ref<Person>;

  @prop()
  password: string;
}

Mateja Petrovic
  • 3,799
  • 4
  • 25
  • 40
  • 2
    Doing just this will not work, at least with the current typegoose 7.2.0. You need to install the auto-populate plugin – Fortune Jun 28 '20 at 00:57
1

Here we have 3 collections shops, owners, documents, gumasta. shops having ObjectId as a reference of owner and documents. But gumasta's reference is in the owner collection document. So to populate sub sub document use below code in typegoose.

     const vehicleEntity = await ShopModel.findOne({ "id": id })
        .populate({
            path: 'owner',
            populate: {
                path: 'gumasta',
                model: 'Gumasta'
            }
        })
        .populate('documents')
        .exec();

Actual structure of shops is

shops{
id: "string"
name: "string"
address_short: "string",
owner: ObjectId('asddsfsdfsdfs34csd7d') // Reference of owner data in owner collection
,documents: [ObjectId('asddsfsdfsdfs34csd7e'), ObjectId('asddsfsdfsdfs34csd7f')]
}

and owner has data below

owners{
 id
 shop_id
 reg_no
 gumasta: ObjectId('sdfsdfsdfs343')
}
1

I had to use something like this:

import { prop, Ref, plugin } from '@typegoose/typegoose';
import mongooseAutoPopulate from 'mongoose-autopopulate';

@plugin(mongooseAutoPopulate as any)
class Person {
  @prop()
  name: string
}

class User {
  @prop({ autopopulate: true, ref: Person })
  person: Ref<Person>;

  @prop()
  password: string;
}

If I try to use it as in docs:

import * as autopopulate from 'mongoose-autopopulate'; 

@plugin(autopopulate as any) 

I get this error: Error: First param to 'schema.plugin()' must be a function, got "object"

Ruben
  • 21
  • 3
0

Typegoose has an autopopulate option on the prop decorator just like @Mateja has said in his answer. However, it doesn't work by itself, you first need to install auto-populate plugin and set up your entity like so...

import { prop, Ref } from '@typegoose/typegoose';
import * as autopopulate from 'mongoose-autopopulate'; // <= import the plugin

@plugin(autopopulate as any) // <= set it up here
class Person {
  @prop()
  name: string
}

class User {
  @prop({ autopopulate: true, ref: Person }) // <= enable the option
  person: Ref<Person>;

  @prop()
  password: string;
}

For more information, check the Typegoose Documentation

Akhil
  • 43
  • 5
Fortune
  • 1,243
  • 2
  • 19
  • 22
0

this is a full example... But I was using type-graphql instead of NestJS. It works Great!!!

import { prop as Property, getModelForClass, Ref, plugin, pre } from '@typegoose/typegoose';
import { ObjectId } from 'mongodb';
import mongooseAutoPopulate from 'mongoose-autopopulate';
import slugify from 'slugify';
import { Field, ID, ObjectType } from 'type-graphql';
import { departmentEnum } from '../../../helpers/validEnums';
import schemaOptions from "../../../helpers/schemaOptions";

@pre<Category>('save', function () {
  this.slug = slugify(this.name,{lower: true});
})

@ObjectType({description:'The category model class'})
@plugin(mongooseAutoPopulate as any)
export default class Category {
  @Field(() => ID, {name: 'id'})
  readonly _id: ObjectId;

  @Field(() => Date)
  readonly createdAt: Date;

  @Field(() => Date)
  readonly updatedAt: Date;

  @Field()
  @Property({required: true, unique: true})
  name!: string;

  @Field(() => departmentEnum)
  @Property({ required: true, enum: departmentEnum })
  department!: departmentEnum;

  @Field()
  @Property({required:true, default:'icon_default.png'})
  icon!: string;

  @Field()
  @Property({ unique: true, index:true })
  slug?: string;

  @Field(() => Boolean)
  @Property({default: false, type: () => Boolean})
  leaf!: boolean;

  @Field(() => Category, { nullable: true })
  @Property({ref: ()=>Category, default: null, autopopulate: { maxDepth: 1 }})
  parent?: Ref<Category>

  @Field(() => [Category], { nullable: 'items' })
  @Property({ref: ()=>Category, default: [], autopopulate: { maxDepth: 1 }})
  children!: Ref<Category>[]
}

export const CategoryModel = getModelForClass(Category,{schemaOptions: schemaOptions});
Ruben
  • 21
  • 3