Returning pagination metadata.
All checks were successful
Deploy Greenlight API / deploy (push) Successful in 2m48s
All checks were successful
Deploy Greenlight API / deploy (push) Successful in 2m48s
This commit is contained in:
@@ -194,15 +194,16 @@ func (m MovieModel) Delete(id int64) error {
|
||||
}
|
||||
|
||||
// GetAll : Returns a slice of movies. Although we're not using them right now, we've set this up to accept the various filter parameters as arguments
|
||||
func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*Movie, error) {
|
||||
func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*Movie, Metadata, error) {
|
||||
// Construct the SQL query to retrieve all movie records.
|
||||
// to_tsvector('simple', title) transforms 'The Breakfast Club' into 'breakfast' 'club' 'the'. The 'simple' parameter's value is the configuration.
|
||||
// plainto_tsquery('simple', $1) takes a search value and turns it into a formatted query term that PostgreSQL full-text search can understand. As an example : "The Club" would result in the query term 'the' & 'club'
|
||||
// The @@ operator is the matches' operator. To continue the example, the query term 'the' & 'club' will match rows which contain both lexemes 'the' and 'club'.
|
||||
// Add an ORDER BY clause and interpolate the sort column and direction. Importantly, notice that we also include a secondary sort on the movie ID to ensure a consistent ordering.
|
||||
// Update the SQL query to include the LIMIT and OFFSET clauses with placeholder parameter values
|
||||
// Update the SQL query to include the window function which counts the total (filtered) records
|
||||
query := fmt.Sprintf(`
|
||||
SELECT id, created_at, title, year, runtime, genres, version
|
||||
SELECT count(*) OVER(), id, created_at, title, year, runtime, genres, version
|
||||
FROM movies
|
||||
WHERE (to_tsvector('simple', title) @@ plainto_tsquery('simple', $1) OR $1 = '')
|
||||
AND (genres @> $2 OR $2 = '{}')
|
||||
@@ -220,12 +221,13 @@ func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*M
|
||||
// And then pass the args slice to QueryContext() as a variadic parameter
|
||||
rows, err := m.DB.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, Metadata{}, err
|
||||
}
|
||||
|
||||
// Importantly, defer a call to rows.Close() to ensure the resultset is closed before GetAll() returns
|
||||
defer rows.Close()
|
||||
|
||||
totalRecords := 0
|
||||
// Initialize an empty slice to hold the movie data.
|
||||
movies := []*Movie{}
|
||||
|
||||
@@ -236,6 +238,7 @@ func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*M
|
||||
|
||||
// Scan the values from the row into the Movie struct. Again, note that we're using the pq.Array() adapter on the genres field here.
|
||||
err := rows.Scan(
|
||||
&totalRecords,
|
||||
&movie.ID,
|
||||
&movie.CreatedAt,
|
||||
&movie.Title,
|
||||
@@ -245,7 +248,7 @@ func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*M
|
||||
&movie.Version,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, Metadata{}, err
|
||||
}
|
||||
|
||||
// Add the Movie struct to the slice.
|
||||
@@ -254,10 +257,14 @@ func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*M
|
||||
|
||||
// When the rows.Next() loop has finished, call rows.Err() to retrieve any error that was encountered during the iteration.
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
return nil, Metadata{}, err
|
||||
}
|
||||
|
||||
// Generate a Metadata struct, passing in the total record count and pagination parameters from the client
|
||||
metadata := calculateMetadata(totalRecords, filters.Page, filters.PageSize)
|
||||
|
||||
// If everything went OK, then return the slice of movies
|
||||
return movies, nil
|
||||
// Include the metadata struct when returning
|
||||
return movies, metadata, nil
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user