chunk 和 chunkById 功能上有区别吗?

InstallmentItem::query()->chunk(100,function(){});
InstallmentItem::query()->chunkById(100,function(){});
桃知夭夭
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 14
leo

这种问题为什么不自己看一看源码呢?

6年前 评论

@leo 好吧,有点懒了,昨天。:smile:

6年前 评论

@leo 因为公司现有的项目中用的是laravel5.1,这个版本里面还没有chunkById,那么我想处理大表 带条件的更新操作时chunk会丢数据,我应该怎么实现呢,leo哥能否给个思路。~

6年前 评论
leo

@AmberLavigne 照着 chunkById 的代码写一下不就可以了么

6年前 评论

@leo :joy:想想也是,研究研究~~~

6年前 评论

自问自答: 实现chunkById() 需求处理大表带条件更新操作。 基于laravel5.1 的command

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use DB;
use App\Model\Comment;
class CompletionCommentTitle extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature =' title:completion_comment_title';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '根据指定条件补全评论title';

    const CHUNK_SIZE = 150;
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        try{
             $this->info('开始处理...');
             $this->chunkById(self::CHUNK_SIZE,function ($comments){
                 $this->info(sprintf('正在补全 ID 范围为 %s 至 %s 的评论title',$comments->first()->id, $comments->last()->id));
                 foreach($comments as $comment){
                     $comment->where('id',$comment->id)->update(['title'=> $this->perpareTitle()]);
                 }
             });
            $this->info('处理结束...');
        }catch(\Exception $e){
            $this->error($e->getMessage() . ',Line:' . $e->getLine());
        }
    }

    /**
     * 需要补全的理出数据
     * @return mixed
     * @throws \Exception
     */
    protected function perpareTitle(){

        $title_arr = [
            'Very flattering',
            'Super cute!',
             'Very nice',
            'Very good',
            'Satisfying',
            'Nice looking',
            'I love it',
            'Fit perfectly',
            'So comfy',
            'Nice',
            'Perfect!',
            'Look very pretty!',
            'Fit very well',
            'Look good',
            'Fantastic',
            'Comfortable',
            'Thanks',
            'Nice material',
            'Good fit',
            'It\'s cute',
            'Good looking',
            'Speedy delivery',
            'So nice and pretty',
            'Well received!',
            'Great quality',
            'Great purchase!',
            'so well made',
            'Very fashionable',
            'Beautiful',
            'High quality',
            'Highly recommend',
            'nice looking',
            'True size',
            'Adorable',
            'Awesome.',
            'nicely made',
            'Feel good on',
            'Excellent',
            'Super comfy!',
            'Fit as expected'
        ];

        $random =  random_int(0,39);
        return $title_arr[$random];
    }

    /**
     * ID分块处理核心代码
     * @param $count
     * @param callable $callback
     * @param string $column
     * @return bool
     */
    protected function chunkById($count, callable $callback, $column = 'id'){
        $lastId = 0;
        do {
            $results = $this->forPageAfterId($count, $lastId, $column)->get();
            $countResults = $results->count();
            if ($countResults == 0){
                break;
            }
            if ($callback($results) === false) {
                return false;
            }
            $lastId = $results->last()->{$column};
            unset($results);
        } while ($countResults == $count);

        return true;
    }

    protected function forPageAfterId($perPage = 15, $lastId = 0, $column = 'id')
    {
        return Comment::query()
            ->where('title','')
            ->where('customer_id',0)
            ->where($column, '>', $lastId)
            ->orderBy($column, 'asc')
            ->take($perPage);
    }
}
6年前 评论

@leo file 老师请教个问题,我使用chunkById批量处理数据报错,但是chunk方法没问题。报错信息In Builder.php line 591:
Illegal operator and value combination.

6年前 评论
leo

@等车的猪 贴代码

6年前 评论

@leo

 MessageLog1::query()->select('orderId', 'shopId')->chunkById(self::CHUNK_SIZE, function ($rows) {
            foreach ($rows as $row) {
//                dd($row->shopId);
                if (!empty($row)) {
                    $shop = Shop::query()->where('shopId', $row->shopId)->first();
                    if ($shop) {
                        CommentsJob::dispatch(['orderId' => $row->orderId, 'brandUserId' => $shop->brandUserId, 'shopId' => $row->shopId]);
                    }
                }
            }
        });

如果改成chunk就不会出问题,表结构也是id自增

6年前 评论
leo

@等车的猪 你的 select() 里需要加上 id 字段

6年前 评论

@leo 好的 老师厉害了。我先试试

6年前 评论

chunkbyid不能用于join情况

5年前 评论
小李世界 3年前

chunkbyid 使用join
'id' in where clause is ambiguous
如果指定id:表名.id,也报错,貌似chunkbyid不支持加表名指定,forPageAfterId(1000, NULL, 'r_svr.id')

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!