Как правильно задать limit для отношения many-many?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Ro7
Сообщения: 71
Зарегистрирован: 2013.08.17, 15:08

Как правильно задать limit для отношения many-many?

Сообщение Ro7 »

Как правильно задать limit для отношения many-many?
Задача: получить все цитаты текущего тега.
Как видно на скриншоте ниже, некоторые запросы получаются большими и долгими, где более 1000 цитат...

Контроллер:

Код: Выделить всё

$oModels = $oTag->getQuotes()->limit(10)->all();
Модель:

Код: Выделить всё

    public function getQuotes(){
        return $this->hasMany(Quote::className(), ['id'=>'quote_id'])
            ->via('quoteTag');
    }


Изображение
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Как правильно задать limit для отношения many-many?

Сообщение lynicidn »

попробуй в выборке сразу с inner join
oTag::find()->with(['quotes' => function($query){ return $query->limit(10); }])
Ro7
Сообщения: 71
Зарегистрирован: 2013.08.17, 15:08

Re: Как правильно задать limit для отношения many-many?

Сообщение Ro7 »

Результат тот же: http://s14.directupload.net/images/140819/k2xwgsng.png
На скриншоте второй запрос.

А если через dataProvider? Третий запрос на скриншоте... Получается та же картина.

Код: Выделить всё

class TagController extends \yii\web\Controller{

    public function actionView($alias){
        $oTag = Tag::find()
            ->with(['quotes' => function($q){ return $q->limit(10); }])
            ->where(['alias'=>$alias])
            ->one();

        $dataProvider = new \yii\data\ActiveDataProvider([
            'query' => $oTag->getQuotes()
        ]);

        echo $this->render('view', ['dataProvider'=>$dataProvider]);

    }
}
lynicidn
Сообщения: 2222
Зарегистрирован: 2014.05.24, 15:12

Re: Как правильно задать limit для отношения many-many?

Сообщение lynicidn »

опишите суть запроса, что надо лимитировать:? дочек или предков?
Ro7
Сообщения: 71
Зарегистрирован: 2013.08.17, 15:08

Re: Как правильно задать limit для отношения many-many?

Сообщение Ro7 »

Ок. Возьмем конкретный участок.

Код: Выделить всё

        $dataProvider = new \yii\data\ActiveDataProvider([
            'query' => $oTag->getQuotes()
        ]); 
getQuotes(), через промежуточную таблицу, возвращается 5000+ записей, за 20 секунд - несколько запросов типа IN (.., .., .., .., .., x5000). Даже если там ставится для постраничной разбивки LIMIT 20, то каждый запрос все равно длинной 1 метр в высоту.
Как в таком случае работать, в первом yii, как-то решалось с criteria.

Как в таком случае лучше работать с отношением many-to-many? Или какие альтернативы
Задача простая получить первую страницу цитат для определенного тега. Модели Tag, Quote. Связаны через промежуточную таблицу.
/tag/view?alias=zhizn
Ro7
Сообщения: 71
Зарегистрирован: 2013.08.17, 15:08

Re: Как правильно задать limit для отношения many-many?

Сообщение Ro7 »

В общем пришел к какому-то результату... хоть и не так элегантно, как хотелось бы.

В yii1 эта задача у меня решена так:

Код: Выделить всё

public function actionViewTag($tag){
    $oTag = QuotesTags::model()->active()->findByAlias($tag);

    $criteria = new CDbCriteria;
    $criteria->with = array('tags'=>array('scopes'=>'active'), 'titlealias');
    $criteria->order = 'ratio DESC';
    $oPages = new CPagination($oTag->getCitsCount());
    $oPages->pageSize = 10;
    
    $oPages->applyLimit($criteria);
    
    $aCits = $oTag->cits($criteria); 

    $this->render($this->oCat->getOption('templateView'), array('aCits'=>$aCits, 'oPages'=>$oPages));
} 
В yii2 пока адекватно получается пока только так:

Код: Выделить всё

    public function actionView($alias)
    {
        $oTag = Tag::find()
            ->where(['alias' => $alias])
            ->one();

        $query = (new \yii\db\Query())
            ->select('*')
            ->from(QuoteTag::tableName())
            ->leftJoin(Quote::tableName(), 'quote_id = id')
            ->where('tag_id = :tag_id', ['tag_id' => $oTag->id])
            ->orderBy('ratio DESC');

        $pages = new Pagination(['totalCount' => $query->count()]);

        $modelsId = $query->offset($pages->offset)
            ->select('id')
            ->limit($pages->limit)
            ->column();

        $models = Quote::find()->where(['id'=>$modelsId])->orderBy('ratio DESC')->all();

        echo $this->render('view', ['models'=>$models]);

    } 
С собственно скриншот, запросы, в каком виде хотелось бы их видеть, и какие они примерно в первом yii, в противовес первому посту темы...
Если будут мысли по этому поводу, буду рад услышать.

Изображение
Ответить