cms查询加载时间长

vlju58qv  于 2021-06-24  发布在  Mysql
关注(0)|答案(1)|浏览(322)

我正在尝试优化这个嵌套查询,它需要很长时间才能加载。
其基本思想是得到属于一个部门的所有系列,中间是属于多个部门和多个系列的产品。表结构
部门*<-->产品<->*系列
在这些模型中,关系的定义如下:部门模型

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'
        ]
    ];

在department模型中,我创建了一个方法来检索属于department的所有序列,这些序列在分析之后会导致一些严重的性能问题

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秒。删除此代码时,请立即删除。
任何建议都将不胜感激。
从表结构来看,我猜这将是为了获得所需结果而运行的适当的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 (以部门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>

部门系列范围。

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(  )];
    }
daolsyd0

daolsyd01#

您可以利用原始查询和 fetched id 在to模型中,您可以编写以下代码。

$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` 你提供的。它似乎在这里工作

相关问题