chunk 和 chunkById 功能上有区别吗?

InstallmentItem::query()->chunk(100,function(){});
InstallmentItem::query()->chunkById(100,function(){});
桃知夭夭
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 14
leo

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

5年前 评论

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

5年前 评论

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

5年前 评论
leo

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

5年前 评论

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

5年前 评论

自问自答: 实现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);
    }
}
5年前 评论

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

5年前 评论
leo

@等车的猪 贴代码

5年前 评论

@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自增

5年前 评论
leo

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

5年前 评论

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

5年前 评论

chunkbyid不能用于join情况

4年前 评论
小李世界 2年前

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

4年前 评论

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