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
and just want to use auto populate
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
and just want to use auto populate
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;
}
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')
}
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"
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
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});