SQL efficiently check if one of a user’s meeting is missing a review with nested relationships

This is my current code to check if a user needs to give a review or not (that works), but it seems a little janky

// This function checks if the user logging in with id has any reviews he needs to fill out
export async function requireUserReviews(id: string) {
    let user = await db.user.findUnique({
        where: {
            id
        },
        include: {
            teacherMeetings: true,
            studentMeetings: true,
            reviewsGiven: true
        }
    })

    if (!user) {
        throw new Error('User not found')
    }

    // An array of all the meetings you need a review for
    let reviews: Meeting[] = []

    const twoHrs = 1000 * 60 * 60 * 2
    user.teacherMeetings.forEach((meeting) => {
        if (
            new Date(meeting.updatedAt) < new Date(Date.now() - twoHrs) &&
            meeting.status !== 'cancelled'
        ) {
            reviews.push(meeting)
        }
    })

    user.studentMeetings.forEach((meeting) => {
        if (
            new Date(meeting.updatedAt) < new Date(Date.now() - twoHrs) &&
            meeting.status !== 'cancelled'
        ) {
            reviews.push(meeting)
        }
    })

    // Filter out all the meetings for which you've already written a meeting for
    reviews = reviews = reviews.filter((meeting) => {
        if (!user) {
            throw new Error('User not found in meeting filter')
        }
        let cond = true

        // Does a linear search from each review given and sees if it's a review for a meeting review you want to give
        user.reviewsGiven.every((review) => {
            if (review.meetingId == meeting.id) {
                cond = false
                return false
            }
            return true
        })

        console.log(meeting.description, cond)
        return cond
    })

    if (reviews.length > 0) {
        console.log('reviews', reviews)
        throw redirect(`/review/${reviews[0].id}`)
    }

    return user
}

Basically what it does is first grab the user from the id of the user. This user, I also grab a list of three relationships from this person (teacherMeetings, studentMeetings, and reviewsGiven). teacherMeetings is a list of all meetings this user has done where he was a teacher, studentMeetings is similar, and reviewsGiven is self-explanatory.

Then I go through each teacherMeeting and studentMeeting seeing if the meeting happened more than two hours ago and wasn’t cancelled. The reason I check if it happened two hours ago and not just now is because I don’t want to interrupt someone’s coding flow if they’re in the zone by forcing a review instantly, so I wait two hours.

If the meeting wasn’t cancelled and happened more than two hours ago, I push it to a reviews array. Afterwards, I filter the reviews array and check to see if I’ve already given a review for each review in the review arrays. I check if I’ve already given a review by checking each current element in review with a list of all reviews I’ve already given. If I’ve already given it, return false so filter filters it out. Keep the ones where I haven’t already given a review.

This is basically a o(n*m) sweep right here, n for # of reviews you should give and another m for # of reviews you’ve already given. Both n and m are equal if you’ve successfully given all the reviews you should. O(n^2) solution seems very janky, I was wondering if you had any better ideas?

In meeting, I have a relation for reviews[] but I can’t access meeting.reviews since reviews[] is a relation but taking advantage of this turns the o(n^2) mess into just o(1) since there’s only at most two reviews.

I could potentially also take the list of meetings and then for each meetingRequest do a database call and get the list of meetings, but then it becomes n database calls instead of just one, so even though it’s only o(n) * 2 (2 since each reviews only has at most 2 elements), it’s n database calls which may be costly.

What should I do?