NestJS and mongo two way relation between post schema and user schema - mongodb

I am new to nest and mongo I am trying to do a relation where a user schema embeds a posts array with ids of posts and in the posts schema I want to embed the author which is a user schema with the user id but I keep running into this error in my console
Error: Cannot determine a type for the "Post.author" field (union/intersection/ambiguous type was used). Make sure your property is decorated with a "#Prop({ type: TYPE_HERE })" decorator.
this is my code
UserSchema
import { Prop, Schema, SchemaFactory } from "#nestjs/mongoose";
import { Document } from "mongoose";
import { Post, PostSchema } from "src/posts/entities/post.entity";
export type UserDocument = User & Document;
#Schema()
export class User extends Document{
#Prop({ index: true})
name: string;
#Prop([{ type: PostSchema}])
posts: Post[]
}
export const UserSchema = SchemaFactory.createForClass(User)
PostSchema
import { Prop, Schema, SchemaFactory } from "#nestjs/mongoose";
import { Document } from "mongoose";
import { User, UserSchema } from "src/users/entities/user.entity";
export type PostDocument = Post & Document;
#Schema()
export class Post extends Document{
#Prop({index: true})
title: string;
#Prop({index:true})
body: string;
#Prop({type: UserSchema})
author: User;
}
export const PostSchema = SchemaFactory.createForClass(Post)
at the end what I am trying to achive in my database is this
users collection
{
"_id" : "U1",
"name":"user1",
"posts": [
{
"_id": "P1",
"title":"title 1",
"body":"body 1"
}
]
}
posts collection
{
"_id" : "P1",
"title":"title 1",
"body":"body 1",
"author": {
"_id": "U1",
"name":"user1",
}
}
I am trying to embed doucments into each other with the ids so I can read fast and use the ids to update

your user schema have a problem.
the way you define an array is wrong. use this one :
#Prop({type: [PostSchema]})
posts: Post[]

Related

Enable to set ObjectId in nested array in nest.js

I have a module of question, and I want a structure something like
[ { question: 'REFERENCE ID', answer: { start_value: '1', end_value: '2' } } ],
when I try to save it, it save question id as string but I want to store questionId as ObjectId so I can populate it in other request.
while and the complete response I want is:
{
"answer_by": ObjectId(''), // string, should be user reference ID for populating user
"answers": [
{
"question": ObjectId(''), // string, should be user reference ID for populating question
"answer": {
"start_value": "val1",
"end_value": "val2"
}
}
]
}
here is my schema respectively!
import * as mongoose from "mongoose";
import { Person } from "./person.schema";
import { PostMeetingChecklist, PostMeetingChecklistDocument } from "./post-meeting-checklist.schema";
import { Model, Schema as MongooseSchema } from "mongoose";
import { Resource } from "./resource.schema";
#Schema()
export class Answer {
#Prop()
start_value: string;
#Prop()
end_value: string;
}
#Schema()
export class Item {
#Prop({ type: mongoose.Schema.Types.ObjectId, ref: Question.name})
question: string;
#Prop()
answer: Answer;
}
export type QuestionDocument = Question & mongoose.Document;
#Schema({ timestamps: true })
export class Question {
#Prop({ type: mongoose.Schema.Types.ObjectId, ref: User.name })
answer_by: string;
#Prop()
answers: [Item];
}
export const QuestionSchema = SchemaFactory.createForClass(Question);
in mongoDb,it takes answer_by as ObjectId but question as string, how to fixed that?
Further, I also want to populate this like:
{
"answer_by": User Details,
"answers": [
{
"question": Question Details,
"answer": {
"start_value": "5",
"end_value": "10"
}
}
],
"_id": "63f3146f9f84a58be0b32ad8",
"createdAt": "2023-02-20T06:34:23.300Z",
"updatedAt": "2023-02-20T06:34:23.300Z",
"__v": 0
}
Have tried
#Prop()
answers: [{
question:{
type:mongoose.Schema.Types.ObjectId,
ref:"PostMeetingChecklist"
},
answer: Answer
}];
but in vain.

Mongodb select 'field' with condition in Query Population

Let's say that I have three entities Track, Chapter and Episode, a track can contain one or more chapters, a chapter is associated with one track and can contain zero or more episodes.
Track.ts :
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
import * as mongoose from 'mongoose';
import { Chapter } from './chapter.entity';
#Schema({
timestamps: true,
})
export class Track extends Document {
...
#Prop({
type: [mongoose.Schema.Types.ObjectId],
ref: 'Chapter',
})
chapters: [Chapter];
}
export const TrackSchema = SchemaFactory.createForClass(Track);
Chapter.ts :
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
import * as mongoose from 'mongoose';
import { Track } from './track.entity';
import { Episode } from './episode.entity';
#Schema({
timestamps: true,
})
export class Chapter extends Document {
...
#Prop({
type: mongoose.Schema.Types.ObjectId,
ref: 'Track',
required: true,
})
track: Track;
#Prop({
type: [mongoose.Schema.Types.ObjectId],
ref: 'Episode',
})
episodes: [Episode];
}
export const ChapterSchema = SchemaFactory.createForClass(Chapter);
What I want is to find a "track" and populate its "chapters" but without selecting the field "episodes" if it is an empty array. I was looking in the docs I found out how to populate documents with condition but nothing about fields, I found out also how to select some fiels but not with condition.
var track = await this.trackModel
.findById(id)
.populate({
path: 'chapters',
select: '-episodes', // this excludes the episodes field, how can I do it with condition
})
.lean();
Thank you for your attention!

Schema.name undefined while making Many-To-One relation reference with Nestjs & MongoDb

I want to attach and see all the posts of the user inside posts property of UserSchema. The user/Author id is getting stored with posts. But when I try the get posts ids
I'm getting the following error.
#Prop([{ type: mongoose.Schema.Types.ObjectId, ref: BlogPost.name }])
^
TypeError: Cannot read properties of undefined (reading 'name')
at Object.<anonymous> (D:\Noum\Data\CYBRNODE\MAN STACK\Cybrnode-Blog-Backend\Cybr-Blog-Nest-Backend\src\schema\user.schema.ts:45:64)
at Module._compile (node:internal/modules/cjs/loader:1126:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
at Module.load (node:internal/modules/cjs/loader:1004:32)
Blog Schema
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { ApiProperty } from '#nestjs/swagger';
import mongoose, { Document } from 'mongoose';
import { User } from 'src/schema/user.schema';
#Schema({ timestamps: true })
export class BlogPost {
#ApiProperty({ required: true })
#Prop({ type: mongoose.Schema.Types.ObjectId, ref: User.name })
author: User;
}
export const postSchema = SchemaFactory.createForClass(BlogPost);
export type postDocument = BlogPost & Document;
User Schema
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { ApiProperty } from '#nestjs/swagger';
import mongoose, { Document } from 'mongoose';
import { BlogPost } from 'src/schema/blog.schema';
#Schema({ timestamps: true })
export class User {
#ApiProperty()
#Prop([{ type: mongoose.Schema.Types.ObjectId, ref: BlogPost.name }])
posts: BlogPost[];
}
export const userSchema = SchemaFactory.createForClass(User);
export type userDocument = User & Document;
Also I've imported UserModule into BlogPostModule and vice versa. And exported the services of both modules.
I've tried with these as well. But Error is same
import { Document, Schema as MongooseSchema } from 'mongoose';
export class User extends Document{
#ApiProperty()
#Prop([{ type: MongooseSchema.Types.ObjectId, ref: BlogPost.name }])
posts: BlogPost[];
}
export const userSchema = SchemaFactory.createForClass(User);
export type userDocument = User & Document;

MongoDB NestJS API dies if a #Prop is set to ObjectId

So, when i set a #Prop() to ObjectId, the api wont start, but if i set it a string it loads up just fine.
Can you help me? Thanks!
Heres the error:
Schema:
import { Prop, Schema, SchemaFactory } from "#nestjs/mongoose";
import { Document, ObjectId } from "mongoose";
export type FriendRequestDocument = FriendRequest & Document;
#Schema({collection: "friendRequests"})
export class FriendRequest {
#Prop()
author: ObjectId;
#Prop()
friend_id: ObjectId;
#Prop()
request_at: Date;
}
export const FriendRequestSchema = SchemaFactory.createForClass(FriendRequest);
edit:
I figured it out!
import { Prop, Schema, SchemaFactory } from "#nestjs/mongoose";
import mongoose, { Document, ObjectId } from "mongoose";
export type FriendRequestDocument = FriendRequest & Document;
#Schema({collection: "friendRequests"})
export class FriendRequest {
#Prop()
author: mongoose.Types.ObjectId;
#Prop()
friend_id: mongoose.Types.ObjectId;
#Prop()
request_at: Date;
}
export const FriendRequestSchema = SchemaFactory.createForClass(FriendRequest);
I dont really know why its not working.

How to populate Nestjs mongoose schema records

I want to get then enteries from paris air quality, but the thing is that the mongoose schema is nested and I tried to make multiple schemas separated but I don't know wheter it's correct or not.
This is the schema file schemas/air-quality.schema.ts
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
export type AirQualityDocument = AirQuality & Document;
#Schema()
export class Pollution {
#Prop()
ts: string;
#Prop()
aqius: number;
#Prop()
mainus: string;
#Prop()
aqicn: number;
#Prop()
maincn: string;
}
#Schema()
export class Result {
#Prop({ type: Pollution })
pollution: Pollution;
}
#Schema()
export class AirQuality {
#Prop({ type: Result })
result: Result;
#Prop()
datetime: string;
}
export const AirQualitySchema = SchemaFactory.createForClass(AirQuality);
And the result I am getting from mongo is this
PS: it contains multiple entries of the same schema
[
{
"_id": "62dd1b2e744e6bf8cdbcfabd",
"result": {
"_id": "62dd1b2e744e6bf8cdbcfabe"
},
"datetime": "24/07/2022, 11:13:02",
"__v": 0
},
...
]
I don't if the mistake is with the schema or I just need to use autopopulate or something