CRUD条件很慢,有没有其他更快的方法?

时间:2014-02-19 00:40:35

标签: crud atk4

我现在在填充数据库时遇到CRUd问题。 CRUD需要很长时间才能显示出来,因为它需要从M:M表中获取条件。

表: 表用户。有很多标签(hasMany) 表LABLE,有很多用户(hasMany) 中间表UserLabel,有两个hasOne

我想用CRUD显示来自某个标签的所有用户:

MODEL USER:

class Model_User extends Model_Table {
    public $table ='user';
    function init(){
        parent::init(); 
        $this->addField('fbid')->mandatory('Facebook id required');
        ...

        $this->hasOne('Application');
        $this->hasMany('UserLabel');

        $this->addExpression('ratio')->set(function($model,$select){
            return $select->expr('ROUND(([f2] / [f1]) * 100,0)')
            ->setCustom('f1',$model->getElement('sends'))
            ->setCustom('f2',$model->getElement('clicked'));
        });


        $this->addHook('beforeSave',function($m){
                    $m['updated']=$m->dsql()->expr('now()');
                });
    }

模型标签:

class Model_Label extends Model_Table {
    public $table ='label';
    function init(){
        parent::init(); 

        $this->addField('name')->mandatory('Name required');
        $this->addFIeld('application_id')->refModel('Model_Application')->defaultValue($this->api->recall('app'))->system(true);

        $this->addField('active')->type('boolean')->defaultValue('true')->system(true);
        $this->addField('created')->type('timestamp')->defaultValue($this->dsql()->expr('now()'))->system(true);
        $this->addField('updated')->type('timestamp')->system(true);
        $this->hasMany('UserLabel');

        $m = $this->add("Model_UserLabel");
        $this->addExpression("users", $m->dsql()
                ->field($m->dsql()->expr("count(*)"), "all users")
                ->where("label_id", $this->getField("id"))
        );

MODEL USER LABEL

class Model_UserLabel extends Model_Table {
    public $table ='userlabel';
    function init(){
        parent::init(); 

        $this->hasOne('User');
        $this->hasOne('Label'); 
    }
} 

CRDE代码

$c = $this->add('CRUD');
$c->setModel('User', array('name', 'gender','country','city'));
$c->model->addCondition('id','in',
  $this->add('Model_UserLabel')->addCondition('label_id', $_GET['l'])->dsql()->field('user_id')
);

有没有更好的方法呢?

PS。我测试了这个解决方案,它的速度要快得多,但在>周围仍然很慢。 5.000用户:

//get all users
$records = $this->api->db->dsql()->option('distinct')->table('user')->join('userlabel.user_id')->field('user.id')->where('userlabel.label_id',$_GET['l'])->do_getAll();
foreach($records as $record){
  $users .= ','.$record['id'];
}
//create CRUD
$c = $this->add('CRUD');
$c->setModel('User', array('name', 'gender','country','city','sends','clicked','ratio'));
$c->model->addCondition("application_id", $this->api->recall('app'));
$c->model->addCondition('id','in',
    '('.$users.')'
);

1 个答案:

答案 0 :(得分:0)

源代码表达的不仅仅是单词,因此您最好在问题中添加模型定义源代码(可能不完整)。

CRUD / Grid中应该有哪一行?我想这不是1个用户= 1行,但是1个user_label应该是网格中的一行。因此,您应将UserLabel模型设置为网格的模型。

然后在Model_UserLabel中定义一些其他字段,方法是直接从用户和/或标签表中加入它们,如下所示:

class Model_UserLabel extends SQL_Model {
    function init() {
        parent::init();

        // ...

        // fields from user table
        $join_u = $this->join('user', 'user_id');
        $join_u->addField('username'); // this adds fields in current model from joined table
        $join_u->addField('email');

        // fields from label table
        $join_l = $this->join('label', 'label_id');
        $join_l->addField('name');


    }
}

注意:上面的源代码未经测试,仅作为示例放在此处。


修改

尝试这个解决方案 - 几乎和我之前写的一样:

MODEL USER LABEL

class Model_UserLabel extends Model_Table {
    public $table ='userlabel';
    function init(){
        parent::init(); 

        $this->hasOne('User');
        $this->hasOne('Label'); 

        // join user table and add fields to this model from joined user table
        $j = $this->join('user', 'user_id');
        $j->addField('name');
        $j->addField('gender');
        $j->addField('country');
        $j->addField('city');

    }
} 

CRDE代码

$m = $this->add('Model_UserLabel'); // UserLabel here not User
$m->addCondition('label_id', $_GET['l']); // and then this is simple

$c = $this->add('CRUD');
$c->setModel($m, array('name', 'gender','country','city'));

尝试此解决方案并且(几乎)始终 - 代码未经测试。


修改

请尝试此版本 - 它的工作速度更快吗?这基本上是你的P.S.例如,你不应该提取所有用户ID,加入它们然后用很多'in'创建巨大的选择。 如果只使用一个数据库请求就可以完成所有操作而不需要任何额外的数据处理,那么结果应该更快。

// parameters
$app_id = $this->api->recall('app);
$label_id = $_GET['l'];

// prepare model for grid
$m = $this->add('Model_User'); // default User model
$m->_dsql()->option('distinct') // add join to userlabel table + conditions
    ->join('userlabel.user_id')
    ->where('userlabel.label_id', $label_id)
    ->where($m->getField('application_id'), $app_id);

// create CRUD and set it's model. All conditions already set on model above
$c = $this->add('CRUD');
$c->setModel($m, array('name', 'gender','country','city','sends','clicked','ratio'));

注意:上面的源代码经常 - 未经测试:)