I want to make a 'rating' field on my User Entity. The User Entity has a relationship to the Rating Entity, on User there is a field called ratingsReceived, which is an eager load of all Ratings assigned to that User.
I want the 'rating' field on User to be a mean calculation of all rating values which is a field on Rating Entity called 'ratingValue'.
So essentially I want this calculation to be the value of every User 'rating' field:
ratingsReceived.reduce((acc, curr) => acc + curr.ratingValue, 0) / ratingsReceived.length
The fields in question are 'ratingsReceived' on User:
@OneToMany(
() => Rating,
rating => rating.ratingTo
)
ratingsReceived: Rating[];
And 'ratingValue' on Rating:
@Column('decimal')
@Min(0)
@Max(5)
ratingValue: number;
After trial and error, managed to create a workaround for this like so:
// After load is called after the entity loads during find() and similar
// I placed this decorator on my User Entity
@AfterLoad()
calculateRating = async () => {
const result = await getRepository(Rating)
.createQueryBuilder('ratings')
.where('ratings."ratingToId" = :id', { id: this.id })
.getRawAndEntities();
const ratingsAboveZero = result?.entities?.filter(x => parseFloat(x.ratingValue));
const count = ratingsAboveZero.length;
if (count > 0) {
this.rating =
ratingsAboveZero.reduce((acc, curr) => {
return acc + parseFloat(curr.ratingValue);
}, 0) / count;
this.ratingCount = count;
} else {
this.rating = 0;
this.ratingCount = 0;
}
};