Ways to automate the process of updating and retrieving a column that is linked to another column in a

I am currently facing an issue with connecting three entities - Photo, PhotoComment, and PhotoRating. My goal is to allow users to rate a photo, while also enabling multiple comments from various users and multiple ratings (with only one per user). I want the user's rating to be displayed on all comments related to the photos. However, I am struggling to update the rate inside the comments automatically whenever a user changes the photo rate using the ratePhoto method.

Upon calling the ratePhoto method, I noticed in PGAdmin that the photoRatingId is not linked with PhotoComment and fails to update the rate there. Despite this issue, the ratePhoto method functions correctly and saves the photo rate appropriately.

My current tech stack includes NestJS, TypeORM, PostgreSQL, and RxJS. I have a strong preference for working with repositories over query builders.

photos.service.ts

public ratePhoto(photoId: number, ratePhotoDto: RatePhotoDto, user: User): Observable<any> {
        return this.getPhoto(photoId).pipe(
            switchMap((photo: Photo) => from(this.photoRatingRepository.findOneBy({ photo: { id: photo.id }, user: { id: user.id } })).pipe(
                map((photoRating: PhotoRating) => {
                    if (!photoRating) {
                        const newRating: PhotoRating = new PhotoRating();

                        newRating.rate = ratePhotoDto.rate;
                        newRating.user = user;
                        newRating.photo = photo;

                        return this.photoRatingRepository.save(newRating);
                    }

                    photoRating.rate = ratePhotoDto.rate;

                    return this.photoRatingRepository.save(photoRating);
                }),
            )),
        );
    }

photo.entity.ts

@Entity()
export class Photo {
    //...

    @OneToMany(() => PhotoComment, (photoComment: PhotoComment) => photoComment.photo)
    public photoComments: PhotoComment[];

    @OneToMany(() => PhotoRating, (photoRating: PhotoRating) => photoRating.photo)
    public photoRatings: PhotoRating[];
}

photo-comment.entity.ts

@Entity()
export class PhotoComment {
    //...

    @ManyToOne(() => Photo, (photo: Photo) => photo.photoComments, { onDelete: 'CASCADE' })
    public photo: Photo;

    @ManyToOne(() => PhotoRating, (photoRating: PhotoRating) => photoRating.photoComment)
    @JoinColumn({ name: 'rate' })
    public photoRating: PhotoRating;
}

photo-rating.entity.ts

@Entity()
@Unique(['user', 'photo'])
export class PhotoRating {
    //...
    
    @Transform(({ value }) => +value)
    @Column({ type: 'decimal', precision: 3, scale: 2, default: 0 })
    public rate: number;

    @ManyToOne(() => Photo, (photo: Photo) => photo.photoRatings, { onDelete: 'CASCADE' })
    public photo: Photo;

    @OneToMany(() => PhotoComment, (photoComment: PhotoComment) => photoComment.photoRating, { cascade: true })
    public photoComment: PhotoComment;
}

What could be causing this issue?

Answer №1

From my perspective, the issue lies in the fact that the photoComment has not been properly initialized.

To rectify this, insert the following code snippet into the ratePhoto method:

photoRating.photoComment = photoComment;

By doing so, you can ensure that the photoComment property of the photoRating entity is accurately configured.

The revised method should appear as shown below:

public ratePhoto(photoId: number, ratePhotoDto: RatePhotoDto, user: User): Observable<any> {
  return this.getPhoto(photoId).pipe(
    switchMap((photo: Photo) => from(this.photoRatingRepository.findOneBy({ photo: { id: photo.id }, user: { id: user.id } })).pipe(
      map((photoRating: PhotoRating) => {
        if (!photoRating) {
          const newRating: PhotoRating = new PhotoRating();
          newRating.rate = ratePhotoDto.rate;
          newRating.user = user;
          newRating.photo = photo;
          return this.photoRatingRepository.save(newRating);
        }
        photoRating.rate = ratePhotoDto.rate;
        photoRating.photoComment = photoComment;
        return this.photoRatingRepository.save(photoRating);
      }),
    )),
  );
}

Answer №2

After some troubleshooting, I finally got it sorted out. The issue was that although most of the elements were created correctly, my rate was not showing up on the PhotoRating Entity because I forgot to update the PhotoComment Entity. Instead of manually retrieving and saving all comments, I utilized the .update() method and refactored my approach to incorporate transactions and switch from RxJS to promises for better performance. Here is an overview of how my code looks now:

photos.service.ts

// Code snippet for ratePhoto function
// Includes async/await and EntityManager transaction usage

photo.entity.ts

// No significant changes here in the Photo entity

photo-comment.entity.ts

// Modified the PhotoComment entity structure
// Removed JoinColumn as it was unnecessary

photo-rating.entity.ts

// Updates made to the PhotoRating entity
// Removed cascade option from PhotoComment association

With these tweaks, the functionality is now running smoothly and efficiently. Additionally, I fine-tuned the code for scenarios where a user adds a comment to a rated photo, utilizing the .update() method as before.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Update name of an angular 2 component template

Is it possible to dynamically change the component template <FAQ-omni></FAQ-omni> based on a click event in the list? <div class="row"> <div class="col-xlg-4 col-xl-12 col-lg-12 col-md-7 col-sm-12 col-xs-12" title="FAQ" baCard ...

Learning to retrieve the value from a dynamically generated input tag in a TypeScript file

<div *ngFor="let task of arrayList"> <input id="task.fieldName" *ngIf="task.key === 'Others'" type="text" class="form-control"> </div> When dealing with dynamically created input fields based on a condition, the challenge is ac ...

getting TypeScript configured with webpack

I am currently using Typescript to develop a back-end API utilizing graphql and express. To manage the project development and building process, I have implemented webpack. As part of my setup, I am employing raw-loader in order to load graphql schemas an ...

What is the best way to utilize the DISTINCT ON clause in PostgreSQL to retrieve a count of the duplicates as well?

Imagine having a table structured like this: +--------+--------+------+--------+---------+ | A | B | C | g | h | +--------+--------+------+--------+---------+ | cat | dog | bird | 34.223 | 54.223 | | cat | pigeon | goat | ...

Adding URL path in Angular 7's .ts file

I currently have the following code in my component's HTML file: <button mat-flat-button class="mat-flat-button mat-accent ng-star-inserted" color="accent" (click)="playVideo(video)"> <mat-icon [svgIcon]="video.type === 'external' ...

Add an image to a directory with Angular 7

I am having trouble uploading an Image to the assets/ folder using Angular 7. Below is my attempted solution: HTML: <form [formGroup]="form" (ngSubmit)="postData()" class="intro-form-css"> <div class="form-row"> ...

Is it possible to store a TypeScript type predicate in a variable?

Let's consider a type predicate similar to the one shown in the TypeScript documentation: function isFish(pet: Fish | Bird): pet is Fish { return (pet as Fish).swim !== undefined; } Now, imagine we have some code structured like this: function in ...

To ensure the next line only runs after the line above has finished executing, remember that the function is invoked in HTML

my.component.html <button (click)="refresh()">Refresh</button> my.component.ts refresh() { let self = this; self.isRefresh = true; //1st time self.getfun().then(() => { self.isRefresh = false; ...

Unable to retrieve data | Solely impacting mobile devices | Developed with Express, Postgres, and Vue

While my Vue application works flawlessly on desktop, it encounters issues on mobile devices where it fails to fetch data upon loading, resulting in components rendering without any data to display. Experience the app here Explore the complete Github repo ...

Nuxt - asyncData ISSUE: "Variable '$axios' is inferred to have an 'any' type."

Referencing the guidelines provided at Encountering an error logged in console while executing yarn dev: ERROR ERROR in pages/index.vue:51:21 ...

The angular framework is unable to assign a value to the property 'xxxx' because it is currently undefined

I am currently working on a simple application using Ionic (angular) and I am facing an issue with the error message: Cannot set property 'origin' of undefined Below is the interface for Product.ts: export interface Products{ id: number ...

Error [ERR_MODULE_NOT_FOUND]: Unable to locate the specified module (TypeScript/TypeOrm)

I'm encountering an issue where the content of my database is not being printed when using an entity with TypeScript/TypeOrm. Here's the code I have: Main file : import { createConnection, getManager ,getConnectionOptions } from 'typeorm&a ...

Angular is unable to retrieve the /page resource

I attempted to deploy an angular application on Google Cloud, however, I encountered an issue where only the home page was properly deployed. Whenever I tried clicking on any other button in the navigation bar, it resulted in an error message stating "Erro ...

The error message "Error: Node.js heap out of memory" occurred while running the npm build command in NestJS

I'm encountering a problem with my Nest js API. While everything works perfectly when I build it locally and can start the development server without any issues, I face difficulties building or starting the server when deploying to my hosting server. ...

Understanding the export and export default behavior in JavaScript

I am in the process of developing a NodeJS and Express application and I require a configuration module that executes only once during startup and then provides a serverConfig object to any other modules that may need these values. This is what I have so f ...

What is the best method for hashing CSS module class names in the latest version of Nextjs?

Is there a way to modify/minify/encrypt/conceal/obscure CSS class names in Next JS? I've attempted various methods, including referencing this discussion. Encountering the following issues while experimenting with this proposed solution: yarn bu ...

What is the best method for obtaining weekly cohort counts using SQL?

To assign each user a user_type of either ‘A’, ‘B’, or ‘C’ based on their visits to a specific page over a 4-month period, and then calculate the number of users per user_type per week. Each week in the query represents an 8-week cohort, start ...

Improprove the performance of an array of objects using JavaScript

Hello there, I am currently in the process of creating an array. this.data = [{ label: 'Total', count: details.request.length, }, { label: 'In-Progress', count: details.request.filter((obj) => obj.statusId === 0 || ob ...

A guide on harnessing the power of a promise in Typescript

Although I am familiar with async/await/then, I recently stumbled upon something new that sparked my curiosity: Consider the following function: HelloWorld():Promise<string> { return new Promise(resolve => { setTimeout(() => { ...

Error message: The Luxon DateTime was not recognized as a valid Luxon DateTime object

I'm having trouble understanding the workings of Luxon... I'm using Redux Toolkit to initialize the state as shown below import {DateTime} from "luxon" interface TestStateProps { startDate: DateTime, endDate: DateTime, } const ...