Mongodb Sub-document is not automatically generating object id Typegoose/ mongoose

352 views Asked by At

I am building a web application using TypeScript, Node JS and MongoDB. I am using Typegoose, https://www.npmjs.com/package/@typegoose/typegoose for interacting with MongoDB. Now, I am trying to get Typegoose/ mongoose to automatically generate object ID for sub-document model. You can see the dummy code below.

I have the models as follow

import { Types } from 'mongoose';
import { getModelForClass, prop } from '@typegoose/typegoose';

class PageContract {
  @prop({ required: true, type: String })
  public title!: string;

  @prop({ required: false, type: String })
  public description?: string;

  @prop({ required: false, type: String })
  public externalLink?: string;

  @prop({ required: true, type: Date, default: Date.now() })
  public createdAt!: Date;
}

export class SubPage extends PageContract {
  @prop({ required: true, type: Types.ObjectId })
  public _id!: Types.ObjectId;
}

export class Page extends PageContract {
  @prop({ required: false, type: Array })
  public subPages?: SubPage[];

  @prop({ required: false, type: Date })
  public publishedAt!: Date;

  @prop({ required: false, type: Date })
  public draftedAt!: Date;

  @prop({ required: false, type: Date })
  public unpublishedAt!: Date;
}

export const PageModel = getModelForClass(Page);
export const SubPageModel = getModelForClass(SubPage);

As you can see in the code snippet above, Page has many SubPage models. I am creating page with sub-pages as below.

export const createPage = ({
  title,
  description,
  externalLink,
  subPages,
  status
}: SavePagePayload): Promise<DocumentType<Page>> => {
  const docSubPages: SubPage[] = [];
  if (subPages && subPages.length > 0) {
    subPages.every(({ title, description, externalLink }) => {
      const subPage = new SubPage();
      subPage._id = new Types.ObjectId();
      subPage.title = title;
      subPage.description = description;
      subPage.externalLink = externalLink;
      docSubPages.push(subPage);
    });
  }

  const statusFields = getNextStatusTimestamps(status);

  return PageModel.create({
    ...statusFields,
    title,
    description,
    externalLink,
    subPages: docSubPages
  });
};

As you can see in the code, I have to explicitly generate object id for each sub page as follow because Typegoose does not automatically generates it for me.

subPage._id = new Types.ObjectId();

How can I get Typegoose to automatically generate object ID for sub-document model?

1

There are 1 answers

0
hasezoey On

As you can see in the code, I have to explicitly generate object id for each sub page as follow because Typegoose does not automatically generates it for me.

@prop({ required: true, type: Types.ObjectId })
public _id!: Types.ObjectId;

You are explicitly overwriting the default _id behavior if you add a @prop to a automatically generated property. The fix is to remove the @prop decorator line unless you need to change the type.

PS: i have also updated the typegoose documentation to better explain this case in Change _id Type.

@prop({ required: false, type: Array })
public subPages?: SubPage[];

dont ever declare your array type with the generic Array type, this will result in a Mixed array, read Array Types & Fields.
(currently you are basically saying that property is a array, but without any validation)