nestjs-query
nestjs-query copied to clipboard
[Question] How to add relation in embed document
Dear @doug-martin, I'm facing with relation issue using typegoose. How can I add relations in embed document if I have a schema like this:
import { Prop, modelOption, Ref } from '@typegoose/typegoose';
import { Base } from '@typegoose/typegoose/lib/defaultClasses';
@modelOptions({ schemaOptions: { timestamps: true } })
export class TodoItemEntity extends Base {
@Prop({ required: true })
title!: string;
@Prop()
description?: string;
@Prop({ required: true })
completed!: boolean;
@Prop({ default: Date.now })
createdAt!: Date;
@Prop({ default: Date.now })
updatedAt!: Date;
@Prop()
tags!: {
isPrimary: boolean;
tag: Ref<TagEntity>;
}[];
@Prop({ default: 0 })
priority!: number;
@Prop()
createdBy?: string;
@Prop()
updatedBy?: string;
public get id(): string {
// eslint-disable-next-line no-underscore-dangle
return this._id.toHexString();
}
}
@doug-martin Can you help me to answer this question? I need it urgent.
@viennv1709 - You mean for the tags?
You'd need to create a second class and in that class, you'd have what you have in the object.
Scott
@smolinari How can I filter with array of embed documents?
@viennv1709 - It doesn't look like that is possible. What are you trying to accomplish? Can you explain the use case?
Scott
@smolinari OK. Let me explain. I have a user entity that allow users can add more their emails. And I want to to query the user with the emails that exists in list. For example user A has 2 emails: [email protected] and [email protected]. I would like to query the user with email is [email protected] with structure like this:
import { Prop, ModelOptions } from '@typegoose/typegoose';
import { Base } from '@typegoose/typegoose/lib/defaultClasses';
import { Types } from 'mongoose';
export enum Gender {
MALE,
FEMALE,
NONBINARY,
UNKNOWN,
}
export enum NotificationEmail {
ACCOUNT,
UPDATES,
PROMOTIONS,
}
export enum ColorMode {
LIGHT,
DARK,
}
export enum UserRole {
ADMIN,
USER,
}
export enum TfaMethod {
NONE,
SMS,
TOTP,
EMAIL,
}
@ModelOptions({ schemaOptions: { _id: false } })
export class Email {
@Prop({ required: true, index: true })
email: string;
@Prop({ required: true, index: true })
emailSafe: string;
@Prop({ default: false })
isPrimary: boolean;
@Prop({ default: false })
isVerified: boolean;
}
@ModelOptions({ schemaOptions: { _id: false } })
export class Address {
@Prop({ required: true, trim: true })
country: string;
@Prop({ required: true, trim: true })
state: string;
@Prop({ required: true, trim: true })
city: string;
@Prop({ required: true, trim: true })
street: string;
@Prop({ required: true, trim: true })
zipCode: string;
@Prop({ default: false })
isPrimary: boolean;
}
@ModelOptions({ schemaOptions: { _id: false } })
export class Preferences {
@Prop({ default: 'en-us' })
language: string;
@Prop({ default: 'America/Los_Angeles' })
timezone: string;
@Prop({ enum: NotificationEmail, default: NotificationEmail.ACCOUNT })
notificationEmail: NotificationEmail;
@Prop({ enum: ColorMode, default: ColorMode.LIGHT })
colorMode: ColorMode;
}
@ModelOptions({ schemaOptions: { _id: false } })
export class Tfa {
@Prop({ enum: TfaMethod, default: TfaMethod.NONE })
method: TfaMethod;
@Prop()
secret?: string;
}
@ModelOptions({ schemaOptions: { timestamps: true, collection: 'users' } })
export class UserEntity implements Base {
_id: Types.ObjectId;
id: string;
@Prop({ required: true, index: true })
name: string;
@Prop()
password?: string;
@Prop({ enum: Gender, default: Gender.UNKNOWN })
gender: Gender;
@Prop({ default: 'https://unavatar.now.sh/fallback.png' })
avatarUrl: string;
@Prop({ index: true, sparse: true })
phoneNumber?: string;
@Prop({ default: false })
phoneNumberVerified: boolean;
@Prop({ type: () => [Email], default: [] })
emails: Email[];
@Prop({ type: () => [Address], default: [] })
addresses: Address[];
@Prop({ type: () => Preferences, default: new Preferences() })
preferences: Preferences;
@Prop({ type: () => Tfa, default: new Tfa() })
tfa: Tfa;
@Prop({ enum: UserRole, default: UserRole.USER })
role: UserRole;
@Prop({ default: false })
active: boolean;
@Prop({ default: Date.now })
createdAt: Date;
@Prop({ default: Date.now })
updatedAt: Date;
}
Yeah, unfortunately, nestjs-query doesn't support filtering on arrays as I can tell (and yet). So, best bet for now is to create a custom service and add such a method using model.find
.
Scott