jeudi 7 mars 2019

How to design filter and reduce SQL queries?

There is a sports site and it has a lot of blocks with the same filter (Season, League, Group, Sex, Tour). Each block has own filter, that is, not one filter throughout the site. Also, some parameters may or may not be present in some blocks. For example, in the "Matches of the Day" block it makes no sense to show a filter by season, because today only the matches of the current season.

Also for the filter there is a list of priority parameters in case the user did not specify a filter. First try to find in each block the data of the men's Premier League, then the women's, etc. The priority is given in this order:

  1. Men's Premier League
  2. Women's Premier League
  3. Men's Super League
  4. Women's Super League
  5. Men's Premier League "A"
  6. Women's Major League "A"
  7. Men's Major League "B"
  8. Women's Major League "B"
  9. Men's Major League "C"
  10. Men's Premier League "D"

Also in the filter should be available to the choice of all the options that are available for this block. At the moment, the filter class implements the following interface

<?php

namespace App\Filter;

use App\Exceptions\FilterException;
use App\Models\{Season, League, Sex, Tour, Group};

/**
 * Filter interface
 * Interface FilterInterface
 * @package App\Filter
 */
interface FilterInterface
{
    /**
     * FilterInterface constructor.
     * @param array $filter
     */
    public function __construct(array $filter = []);

    /**
     * @param $property
     * @return mixed
     */
    public function __get($property);

    /**
     * @param $property
     * @param Season|League|Sex|Group|Tour $value
     */
    public function __set($property, $value);

    /**
     * @throws FilterException
     * @return int
     */
    public function getSeasonId() : int;

    /**
     * @param Season | int $season
     * @throws FilterException
     * @return FilterInterface
     */
    public function setSeason($season = null) : FilterInterface;

    /**
     * @throws FilterException
     * @return int
     */
    public function getLeagueId(): int;

    /**
     * @param League | int $league
     * @throws FilterException
     * @return FilterInterface
     */
    public function setLeague($league = null) : FilterInterface;

    /**
     * @throws FilterException
     * @return int
     */
    public function getSexId(): int;

    /**
     * @param Sex | int $sex
     * @throws FilterException
     * @return FilterInterface
     */
    public function setSex($sex = null): FilterInterface;

    /**
     * @throws FilterException
     * @return int
     */
    public function getTourId(): int;

    /**
     * @param Tour | int $tour
     * @throws FilterException
     * @return FilterInterface
     */
    public function setTour($tour = null): FilterInterface;


    /**
     * @throws FilterException
     * @return int
     */
    public function getGroupId(): int;

    /**
     * @param Group | int $group
     * @throws FilterException
     * @return FilterInterface
     */
    public function setGroup($group = null): FilterInterface;


    /**
     * Get list of the options by key
     * @param $key
     * @return array
     */
    public function getOptions($key) : array;


    /**
     * Add option to filter by key
     * @param $key
     * @param $value
     * @throws FilterException
     * @return FilterInterface
     */
    public function addOption($key, $value) : FilterInterface;

    /**
     * Remove option from filter by key
     * @param $key
     * @param $value
     * @throws FilterException
     * @return FilterInterface
     */
    public function removeOption($key, $value) : FilterInterface;

    /**
     * Is filter has property?
     * @param $property
     * @return boolean
     */
    public function has($property) : bool;

    /**
     * Hide property from result array
     * @param $property
     * @return FilterInterface
     */
    public function hide($property) : FilterInterface;

    /**
     * Get filter as array
     * @return array
     */
    public function get() : array;
}

All blocks that work with the filter are inherited from the abstract class.

<?php

namespace App\Schedule;

use App\Filter\FilterInterface;

abstract class ScheduleAbstract
{
    /**
     * @var FilterInterface $filter
     */
    protected $filter;

    public function __construct(FilterInterface $filter)
    {
        $this->filter = $filter;
    }

    public function getFilter() : FilterInterface
    {
        return $this->filter;
    }

    public function setFilter(FilterInterface $filter)
    {
        $this->filter = $filter;
    }

    public function getFilterArray() : array
    {
        return $this->filter->get();
    }


    abstract public function get() : array;
}

In other words, each block must implement only the get () method.

So, the list of problems:

1. How to fill the filter options?

It turns out that for each block I need to make a request to get all the records, then cycle through the filter through addOption, but there are a lot of records, and even more blocks. In this case, the site simply will not cope with so many SQL queries and cycles.

2. How best to implement priority?

Is it easier to make one large query and look for data by priority or make queries in a loop until the data is found?

Aucun commentaire:

Enregistrer un commentaire