Skip to content

Commit 83108f8

Browse files
committed
chunk查询方法使用lazy方法重写并优化实现
1 parent 94d34d6 commit 83108f8

File tree

2 files changed

+39
-42
lines changed

2 files changed

+39
-42
lines changed

src/db/LazyCollection.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,4 +577,36 @@ public function whereNotBetween(string $field, $value)
577577
{
578578
return $this->where($field, 'not between', $value);
579579
}
580+
581+
/**
582+
* 分块处理数据
583+
* @param int $size 块大小
584+
* @return static
585+
*/
586+
public function chunk(int $size)
587+
{
588+
if ($size <= 0) {
589+
throw new \InvalidArgumentException('Size should be greater than 0');
590+
}
591+
592+
return new static(function () use ($size) {
593+
$chunk = [];
594+
$count = 0;
595+
596+
foreach ($this->getIterator() as $key => $value) {
597+
$chunk[$key] = $value;
598+
$count++;
599+
600+
if ($count >= $size) {
601+
yield new Collection($chunk);
602+
$chunk = [];
603+
$count = 0;
604+
}
605+
}
606+
607+
if (!empty($chunk)) {
608+
yield new Collection($chunk);
609+
}
610+
});
611+
}
580612
}

src/db/Query.php

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace think\db;
1515

1616
use PDOStatement;
17+
use think\Collection;
1718
use think\db\exception\DbException as Exception;
1819
use think\model\LazyCollection as ModelLazyCollection;
1920

@@ -552,51 +553,15 @@ public function stream(callable $callback, bool $unbuffered = false): int
552553
*/
553554
public function chunk(int $count, callable $callback, string | array | null $column = null, string $order = 'asc'): bool
554555
{
555-
if ($count < 1) {
556-
throw new Exception('The chunk size should be at least 1');
557-
}
558-
559-
$options = $this->getOptions();
560-
$column = $column ?: $this->getPk();
561-
$bind = $this->bind;
562-
563-
if ($this->getOption('order') || !is_string($column)) {
564-
$times = 1;
565-
$resultSet = $this->options($options)->page($times, $count)->select();
566-
} else {
567-
$resultSet = $this->options($options)->order($column, $order)->limit($count)->select();
568-
569-
if (str_contains($column, '.')) {
570-
[$alias, $key] = explode('.', $column);
571-
} else {
572-
$key = $column;
573-
}
574-
}
575-
576-
while (true) {
577-
if (false === call_user_func($callback, $resultSet)) {
556+
$chunks = $this->lazy($count, $column, $order)->chunk($count);
557+
558+
foreach ($chunks as $chunk) {
559+
$result = $callback($chunk);
560+
if ($result === false) {
578561
return false;
579562
}
580-
581-
if (count($resultSet) < $count) {
582-
break;
583-
}
584-
585-
if (isset($times)) {
586-
$times++;
587-
$query = $this->options($options)->page($times, $count);
588-
} else {
589-
$end = $resultSet->pop();
590-
$lastId = is_array($end) ? $end[$key] : $end->getData($key);
591-
592-
$query = $this->options($options)
593-
->limit($count)
594-
->where($column, 'asc' == strtolower($order) ? '>' : '<', $lastId);
595-
}
596-
597-
$resultSet = $query->bind($bind)->order($column, $order)->select();
598563
}
599-
564+
600565
return true;
601566
}
602567

0 commit comments

Comments
 (0)