【问题标题】:Use faker in laravel when inserting thousand of records插入数千条记录时在laravel中使用faker
【发布时间】:2021-09-23 21:42:14
【问题描述】:

我有一个关于 laravel faker 的问题,我正在寻找使用播种机插入数千条记录的教程

这是我的 PostSeeder.php:

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Post;
use App\Models\User;

class PostSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {            
        Post::factory(10)->create();
    }
}

这里我插入了10个帖子,但是我需要测试数千或数百万条记录,所以我看到了一个教程并修改了播种器

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Str;

class PostSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {        
        
        $users= collect(User::all()->modelKeys());
        $data = [];

        for ($i = 0; $i < 100000; $i++) {
            $data[] = [
                'body' => Str::random(50),
                'image' => 'https://via.placeholder.com/640x480.png/0077dd?text=inventore',
                'user_id' => $users->random(),
                'created_at' => now()->toDateTimeString(),
                'updated_at' => now()->toDateTimeString(),
            ];
        }

        $chunks = array_chunk($data, 10000);

        foreach ($chunks as $chunk) {
            Post::insert($chunk);
        }
        
    }
}

使用这种方法,我可以更快地插入数千条记录,但问题是我没有正确插入正文和图像字段

我想尝试一下faker,在我的工厂我有这个:

PostFactory.php

<?php

namespace Database\Factories;

use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Post::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'body' => $this->faker->text,
            'image' => $this->faker->imageUrl(),
            'user_id' => function() {
                return User::factory()->create()->id;
            }
        ];
    }
}

我想在 PostSeeder 中使用类似这些方法的伪造方法,但我不能,我该怎么办?谢谢。

编辑:

我试过了:

public function run(Faker $faker)
    {                
        
        $users= collect(User::all()->modelKeys());
        $data = [];

        for ($i = 0; $i < 50000; $i++) {
            $data[] = [
                'content' => $faker->text,
                'image_path' => $faker->imageUrl(),
                'user_id' => $users->random(),
                'created_at' => now()->toDateTimeString(),
                'updated_at' => now()->toDateTimeString(),
            ];
        }

        $chunks = array_chunk($data, 5000);

        foreach ($chunks as $chunk) {
            Post::insert($chunk);
        }
        
    }

我收到了这条消息: PDOException::("SQLSTATE[HY000]: 一般错误:2006 MySQL 服务器已消失") 但是当我尝试使用更少的记录时它可以工作,所以,我像这样更改了播种机:

$users= collect(User::all()->modelKeys());
$posts = Post::factory(10)->create();        
$posts = collect($posts->only(['content','image_path']));
...
...
'content' => $posts->random()->content,
'image_path' => $posts->random()->image_path
...

这不起作用,它得到了这个错误: 您请求了 1 项,但只有 0 项可用。 看起来 $posts->only(['content','image_path']) 无法正常工作。所以我尝试了这个:

Post::factory(10)->create();
$tweets = Tweet::select(['content','image_path'])->get();
...
'content' => $posts->random()->content,
'image_path' => $posts->random()->image_path
...

它再次适用于一些记录,但是当我尝试使用数千条记录时,我再次收到此错误: PDOException::("SQLSTATE[HY000]: 一般错误:2006 MySQL 服务器已消失")

我能做什么?谢谢

【问题讨论】:

    标签: php laravel testing faker


    【解决方案1】:

    由于模型工厂创建内存中的对象,由于内存使用量大,它不适合大型种子。

    但您可以使用Faker 进行数据生成:

    use Faker\Generator as Faker;
    class PostSeeder extends Seeder
    {
        public function run(Faker $faker)
        {
            $users= collect(User::all()->modelKeys());
            $data = [];
    
            for ($i = 0; $i < 100000; $i++) {
                $data[] = [
                    'body' => $faker->text,
                    'image' => $faker->imageUrl(),
                    'user_id' => $users->random(),
                    'created_at' => now()->toDateTimeString(),
                    'updated_at' => now()->toDateTimeString(),
                ];
            }
    
            $chunks = array_chunk($data, 10000);
    
            foreach ($chunks as $chunk) {
                Post::insert($chunk);
            }
        }
    }
    

    【讨论】:

    • 从 MySql 配置中减小分块大小或增加 max_allowed_packet
    • 我尝试减小分块大小,现在它可以工作了,谢谢,但我仍然想知道为什么会显示错误:$tweets = collect($tweets->only(['content','image_path'] ));
    • @Felipe only 集合的功能,从集合中选择键,但是你拥有的是集合的集合(推文列表),所以它不会那样工作,你应该使用类似$tweets-&gt;map-&gt;only(['content','image_path']);
    猜你喜欢
    • 2016-05-23
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 2016-12-31
    • 2018-12-03
    • 2013-12-13
    相关资源
    最近更新 更多