Октябрь cms долгое время загрузки для запроса

0

Я пытаюсь оптимизировать этот вложенный запрос, который занимает очень много времени для загрузки.

Основная идея состоит в том, чтобы получить все серии, принадлежащие отделу, в середине своих продуктов, принадлежащих многим отделам и многим сериям. структура таблицы

отделы * <-> * продукты * <-> * серия

В моделях отношения определяются следующим образом:

public $belongsToMany  = [
      'products' => [
        '\depcore\parts\Models\Product',
        'table' => 'depcore_parts_products_departments',
      ],
      // 'series' => [
      //   '\depcore\parts\Models\Series',
      //   'table' => 'depcore_parts_products_series',
      // ]
    ];

Модель серии

public $hasMany = [
      'products' => [
        '\depcore\parts\Models\Product',
        'table' => 'depcore_parts_products_departments',
      ]
    ];

Модель продукта

public $belongsToMany = [
      'series' => [
        'depcore\parts\Models\Series',
        'table' => 'depcore_parts_products_series',
        'order' => 'name',
        ],
      'departments' => [
        'depcore\parts\Models\Department',
        'table' => 'depcore_parts_products_departments',
        // 'order' => 'name'
        ]
    ];

В модели Департамента я создал метод для извлечения всех серий, принадлежащих отделу, который после анализа вызывает некоторые серьезные проблемы с производительностью

public function series (){

      $seriesArray = array( );
      $products = $this->products()->remember(100)->get();
      foreach ($products as $product) {
        $productSeries = $product->series()->remember(100)->get();
        foreach ($productSeries as $series) {
            if (!isset($seriesArray[$series->id]) and $series->published )
                $seriesArray[$series->id] = $series;
        }
      }

     return \Illuminate\Database\Eloquent\Collection::make($seriesArray);

    }

Я могу сказать, что это можно сделать с использованием сырого SQL или лучшей реализации в активной записи, но я застрял на обоих.

Я добавил метод remember() позже, но без каких-либо результатов. Сейчас время загрузки веб-страницы составляет около 20 секунд. при удалении этого кода ist мгновенно.

Любые советы приветствуются.

Из структуры таблицы я предполагаю, что это будет подходящая команда SQL (команды) для запуска, чтобы получить необходимый результат

SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = 3);

Этот запрос выполняется только на промежуточных таблицах и получает правильные результаты (в phpmyadmin) series_id (в качестве примера используется пример department_id = 3)

Используя код Hardik Satasiya, мне пришлось сменить пару строк, или представление не показало бы серию только пустых строк.

public function series (){

        $sql = 'SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = :dep_id)';

        $data = ['dep_id' => $this->id];
        $query = \DB::select($sql, $data);
        $data = $query;

        $ids = array();
        // I had to rewrite this pare and make it more inelegant still 
        // but the refresh method appeared to made it step out the execution cycle 
        foreach ($data as $key => $value) {
            $ids[] = $value->series_id;
        }

        // in $data we are passing only id information
        // so this records have only id, not db all attributes
        // what ever you pass in $data will become model attributes if its in list
        $collection = \depcore\parts\Models\Series::hydrate($ids);
        return Series::published()->whereIn('id',$ids)->get();

    }

Частичный блок

<div class="element-grid">
    <h4 {% if hideChildren|length and departmentModel.id not in filters.departments %} class='inactive' {% endif %}  ><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}">{{ departmentModel.name }}</a></h4>
    {% if not hideChildren|length %}
    <div class="list">
      <div class="block left-block">
          {% if departmentModel.getChildren|length %}
              <ul class='departments'>
                {% for child in departmentModel.getChildren %}
                     {% if child.published %}
                        <li><strong><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}&Filter[departments][]={{ child.id }}">{{ child.name }}</a></li></strong>
                     {% endif %}

                {% endfor %}
              </ul>
          {% endif %}
         <ul class="series">
           {% for series in departmentModel.departmentSeries.series|slice(0,10) %}
             <li><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}&{{ departmentModel.departmentSeries.childrenString }}&Filter[series][]={{ series.id }}">{{ series.name }}</a></li>
           {% endfor %}
         </ul>
        </div>
        <div class="block right-block">
             <ul class="series series-right">
                {% for series in departmentModel.departmentSeries.series|slice(10,length) %}
                    <li><a href="{{ url('/')}}/parts?Filter[departments][]={{ departmentModel.id }}&{{ departmentModel.departmentSeries.childrenString }}&Filter[series][]={{ series.id }}">{{ series.name }}</a></li>
                {% endfor %}
             </ul>
        </div>
    </div>
    <img src="{{ departmentModel.image.file_name | media }}" alt="">
    {% endif %}
</div>

Область scopeSeries.

public function scopeDepartmentSeries( $query ){
        $children = $query->getModel()->getChildren();
        // dd($children);
        if ( count( $children ) > 0 ) {
            $seriesArray = array (  );

            foreach ($children as $child) {
                $childrenIds[] = 'Filter[departments][]='.$child->id;

                foreach ($child->series (  ) as $series) {

                    if (!in_array($series->id,$seriesArray)) $seriesArray[] = $series->id;

                    if (!array_key_exists($series->id,$seriesArray)) $seriesArray[$series->id] = $series->name;

                }
            } // endforeach children as child
            $childrenString = implode( '&', $childrenIds );
            return ["series" => Series::whereIn ( 'id',$seriesArray )->get (  ),
                    "childrenString" => $childrenString];
        }
        return ["series" => $query->getModel()->series(  )];
    }
  • 0
    depcore_parts_products_departments требуются некоторые детали Series model => таблица depcore_parts_products_series верно? depcore_parts_products_series верно? и затем мы не можем добавить department_id в модель серии, чтобы это не создавало проблем (не уверен насчет вашей архитектуры БД), но мы можем использовать это, чтобы избежать цепочки ссылок, а серии могут направлять точечные отделы вместо прохождения по продуктам.
  • 0
    это просто моя точка зрения, может быть, у вас есть какой-то другой вариант использования, если у вас есть другой вариант использования и комментарии выше не помогли, тогда мы можем написать raw sql просто дайте нам знать, чтобы мы могли подготовить raw sql
Показать ещё 3 комментария
Теги:
activerecord
octobercms
octobercms-plugins

1 ответ

1

вы можете использовать Raw-запросы и преобразовать fetched id в модель, вы можете написать этот код.

$sql = 'SELECT DISTINCT series_id FROM depcore_parts_products_series WHERE product_id IN (SELECT DISTINCT product_id FROM depcore_parts_products_departments WHERE department_id = :dep_id');

$data = ['dep_id' => 2];
$query = \DB::select($sql, $data);
$data = $query;

foreach ($data as $model) {
    $ids[] = $model->series_id;
}

$returnData = Series::whereIn('id',$ids)->get();
// dd($returnData);

return $returnData;

если вы найдете какие-либо трудности, прокомментируйте это.

Обновить

моя модель отдела

use \October\Rain\Database\Traits\SimpleTree;

public $belongsTo = [
    'parent'    => ['HardikSatasiya\StackDemo\Models\Departments', 'key' => 'parent_id'],
];

public $hasMany = [
    'children'    => ['HardikSatasiya\StackDemo\Models\Departments', 'key' => 'parent_id'],
];

public function series() {

    $sql = 'SELECT DISTINCT series_id FROM hardiksatasiya_stackdemo_product_series WHERE product_id IN (SELECT DISTINCT product_id FROM hardiksatasiya_stackdemo_department_product WHERE department_id = :dep_id)';

    $data = ['dep_id' =>  $this->id];
    $query = \DB::select($sql, $data);
    $data = $query;
    foreach ($data as $model) {
        $ids[] = $model->series_id;
    }

    $returnData = Series::whereIn('id',$ids)->get();
    // dd($returnData);

    return $returnData;
}

public function scopeDepartmentSeries( $query ) {
    $children = $query->getModel()->getChildren();
    //dd($children);
    if ( count( $children ) > 0 ) {
        $seriesArray = array (  );

        foreach ($children as $child) {
            $childrenIds[] = 'Filter[departments][]='.$child->id;

            foreach ($child->series (  ) as $series) {

                if (!in_array($series->id,$seriesArray)) $seriesArray[] = $series->id;

                // if (!array_key_exists($series->id,$seriesArray)) $seriesArray[$series->id] = $series->name;

            }
        } // endforeach children as child
        $childrenString = implode( '&', $childrenIds );
        return ["series" => Series::whereIn ( 'id',$seriesArray )->get (  ),
                "childrenString" => $childrenString];
    }
    return ["series" => $query->getModel()->series(  )];
}

и page code section

function onInit() {
    $departmentModel = \HardikSatasiya\StackDemo\Models\Departments::find(1);
    //dd($departmentModel->getChildren());
    $this['departmentModel'] = $departmentModel;
}

и я использую html/partial вы предоставили. и кажется, что он работает здесь

  • 0
    Это довольно хорошо, но мне пришлось вносить изменения, см. (Второе редактирование), так как при использовании метода обновления функция остановилась, а в представлении исчезли элементы.
  • 0
    хм, вы можете поделиться своим html / частичным кодом
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню