*I'm writing code in nestJs with mongodb. The scenario is that I have 2 modules for Genres and Books. And in mongodb both the Genres and Books are storing different schemas. I have a @Get method which takes an id of a genre and return all the books stored in database. But what I want is that, the function will take id of a genre and should return the books regarding to the genre. For example If I give id of English genre, than the function should just return only the English books. And not all the books present in the database. Please read all the statements and code. And the title of this issue might not be right, you can suggest if you want.
I hope you will understand what I'm trying to ask. And If you need further details about code or anything else, I will provide.
Now the logic what I'm am trying, is following with code
bookschema.ts. Schema for Books. Here the 'genres_id', is the id of the the particular genre id, which a person will give while Posting(@Post) a book along with other book properties.
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
@Schema()
export class Book {
@Prop()
name: string
@Prop()
author: string
@Prop()
price: number
@Prop()
genres_id: string
}
export const bookschema = SchemaFactory.createForClass(Book)
export type bookdocument = Book & Document
library.service.ts(library.service for 'genres'), here in this file I'm trying to implement, getallBooksofSingleGenere(id: any), function to get the books for a particular genre, and I want to write a logic like "find({id : genre_id})". But this logic of mine is not right. I want a logic in this function which will return the books of a particular genre.
2-And also I got an error at run time,not on compile time,saying that "this.book_model.find({})" is not a function. I don't know why the error is comming.
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { BooksService } from './books/books.service';
import { Department, departmentdocument } from './departments-schema';
@Injectable()
export class LibraryService {
constructor(@InjectModel(Department.name) private readonly dep_model: Model<departmentdocument>,private readonly book_model: BooksService) { }
async getalldepartments() {
return this.dep_model.find();
}
async getdepartmentbyid(depID){
return this.dep_model.findById(depID)
}
async getallBooksofSingleGenere(id:any)
{
//return this.book_model.find(id)
//return this.book_model.find({books:id})
//return this.book_model.getallbooks() //this logic returns all the books present in database
return this.book_model.find({});//I want to run this logic somehow.
}
async adddepartment(department) {
const newdepartment = new this.dep_model(department)
return newdepartment.save()
}
async putupdatedepartment(id: string, department: departmentdocument) {
return await this.dep_model.findByIdAndUpdate(id, department)
}
async patchupdatedepartment(id: string, department: departmentdocument) {
return await this.dep_model.findByIdAndUpdate(id, department)
}
async deletedepartment(id: string) {
return await this.dep_model.findByIdAndDelete(id)
}
}
library.controller.ts(genre controller). Here the 2nd @Get, takes an genre id and fetch the document of the genre of the id. the 3rd @Get, checks if the id is of a genre, or not. the 3rd @Get, a check where it make sure that the id must be of a genre's id.
import { Body, Controller, Delete, Get, HttpException, Param, Patch, Post, Put } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { departmentdocument } from './departments-schema';
import { LibraryService } from './library.service';
@ApiTags('Genre')
@Controller('Genres')
export class LibraryController {
constructor(private lib_service: LibraryService) { }
@Get()
async getalldepartments() {
return this.lib_service.getalldepartments()
}
@Get('genres/:depid')
async getdepartmentbyid(@Param('depid') depid: string) {
return this.lib_service.getdepartmentbyid(depid)
}
@Get('booksofperticulargenre/:id')
async getallBooksofSingleGenere(@Param('id') id: string) {
var check = await this.lib_service.getdepartmentbyid(id);
if (check != null) { return this.lib_service.getallBooksofSingleGenere(id) }
else {
throw new HttpException('ID does not match to any Genres,Please Enter a valid Genre ID', 404)
}
}
@Post()
async adddepartments(
@Body() department: string,) {
const adddepartment = await this.lib_service.adddepartment(department)
return adddepartment
}
@Put(':id')
async putupdatedepartment(@Param('id') id: string, @Body() department: departmentdocument) {
const updatedepartments = await this.lib_service.putupdatedepartment(id, department)
return updatedepartments
}
@Patch(':id')
async patchupdatedepartment(@Param('id') id: string, @Body() department: departmentdocument) {
return await this.lib_service.patchupdatedepartment(id, department)
}
@Delete(':id')
async deletedepartment(@Param('id') id: string) {
await this.lib_service.deletedepartment(id);
}
}
WC-LIBRARY(DATABASE) WITH TWO FURTHER SCHEMAS
CodePudding user response:
Those database query calls (find, update..) should be triggered on the Mongoose model. Though the name says book_model, I don't think it is actually a book model since its type is BooksService. Book model should be same as how you inject the dept model.
Is the genre_id something auto generated identifier -or- it points to some other collection (ObjectId) ?
CodePudding user response:
To get the desired scenario solution, I've made three changes.
1.The Constructor in library.sevice.ts should be like this if you want to use mongodb funtions like find() etc.
@Injectable()
export class LibraryService {
constructor(@InjectModel(Department.name)
private readonly dep_model: Model<departmentdocument>,
@InjectModel(Book.name)private readonly book_model: Model<bookdocument>) { }
2.You have to add following code as well that I was missing before.It is like whenever you need to use some other module(the entire module for database purpose) in your services you have to introduce that module and module's schema in the second module's imports(In case I have just 2 modules, so in your case you have to figure it out which module you want to import inside other module).Otherwise you will get an error like 'Make sure the module at index should be in x_module'
@Module({
imports: [BooksModule,
MongooseModule.forFeature([{
name: Department.name,
schema: departmentschema
}]),
MongooseModule.forFeature([{
name: Book.name,
schema: bookschema
}]),
],
3.The function will be like this to get books for particular genre.You can change the id with string type if you get some kind of error. And to understand how database queries work you can visit the link(I would suggest to read documentation briefly and thoroughly) https://docs.mongodb.com/manual/reference/method/db.collection.find/.
async getallBooksofSingleGenere(id:any)
{
return this.book_model.find({genres_id:id})
}