Listing Ratings

The last remaining element on the Movie page is the list of ratings on the right-hand side of the page. Although the count in the header is now accurate, the ratings list being by the API needs to be implemented.

The list of ratings is populated by the GetForMovieAsync() method in the RatingService, which currently returns a hardcoded list of ratings from the fixture ratings.json.

c#
Neoflix/Services/RatingService.cs
public async Task<Dictionary<string, object>[]> GetForMovieAsync(string id, string sort = "timestamp",
    Ordering order = Ordering.Asc, int limit = 6, int skip = 0)
{
    // TODO: Get ratings for a Movie
    return await Task.FromResult(Fixtures.Ratings);
}

In this challenge, you will run the following Cypher statement in a read transaction:

cypher
Get Ratings
MATCH (u:User)-[r:RATED]->(m:Movie {tmdbId: $id})
RETURN r {
    .rating,
    .timestamp,
    user: u {
        .userId, .name
    }
} AS review
ORDER BY r.timestamp DESC
SKIP $skip
LIMIT $limit

Your Task

  • Modify the GetForMovieAsync() method to retrieve the ratings from Neo4j.

  • Remember to auto-close the session and use the ToListAsync() function to convert the result record into native C# types.

Click to reveal the completed GetForMovieAsync() method
c#
Neoflix/Services/RatingService.cs
public async Task<Dictionary<string, object>[]> GetForMovieAsync(string id, string sort = "timestamp",
    Ordering order = Ordering.Asc, int limit = 6, int skip = 0)
{
    await using var session = _driver.AsyncSession();

    return await session.ExecuteReadAsync(async tx =>
    {
        var query = $@"
            MATCH (u:User)-[r:RATED]->(m:Movie {{tmdbId: $id}})
            RETURN r {{
                .rating,
                .timestamp,
                user: u {{
                    .userId, .name
                }}
            }} AS review
            ORDER BY r.{sort} {order.ToString("G").ToUpper()}
            SKIP $skip
            LIMIT $limit";
        var cursor = await tx.RunAsync(query, new {id, skip, limit});
        var records = await cursor.ToListAsync();

        return records
            .Select(x => x["review"].As<Dictionary<string, object>>())
            .ToArray();
    });
}

Testing

To test that this functionality has been correctly implemented, run the following code in a new terminal session:

sh
Running the test
dotnet test --logger "console;verbosity=detailed" --filter "Neoflix.Challenges._13_ListingRatings"

The test file is located at Neoflix.Challenges/13-ListingRatings.cs.

Are you stuck? Click here for help

If you get stuck, you can see a working solution by checking out the 13-listing-ratings branch by running:

sh
Check out the 13-listing-ratings branch
git checkout 13-listing-ratings

You may have to commit or stash your changes before checking out this branch. You can also click here to expand the Support pane.

Verifying the Test

Who was the first user to rate Pulp Fiction?

As part of the test suite, the final test will log the name of the first user to rate the movie Pulp Fiction.

Paste the name of the user the box below without quotes or whitespace and click Check Answer.

  • ✓ Keith Howell

Hint

You can also find the answer by running the following Cypher statement:

cypher
MATCH (u:User)-[r:RATED]->(m:Movie {title: "Pulp Fiction"})
RETURN u.name
ORDER BY r.timestamp ASC
LIMIT 1

Copy the answer without any quotes or whitespace.

Lesson Summary

In this Challenge, you modified the GetForMovieAsync() method on the RatingService to return a paginated list of reviews for a movie from the Neo4j database.

In the next Challenge, you will update the PersonService to return list of actors and directors from Neo4j.