php 插入数千条记录时在laravel中使用faker

wvmv3b1j  于 2023-03-16  发布在  PHP
关注(0)|答案(2)|浏览(93)

我有一个问题与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);
        }
        
    }
}

使用这种方法,我可以更快地插入数千条记录,但问题是我没有正确插入body和image字段
我想尝试一些东西与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);
        }
        
    }

我收到了这条信息:PDO异常错误::(“SQLSTATE[HY 000]:一般错误: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
...

它同样适用于少数记录,但当我尝试处理数千条记录时,我再次得到这个错误:* PDO异常::(“SQLSTATE[HY 000]:一般错误:2006 MySQL服务器已关闭”)*
我能做什么?谢谢

biswetbf

biswetbf1#

由于模型工厂创建内存中的对象,因此会占用大量内存,因此不适用于大型种子。
但是您可以使用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);
        }
    }
}
4nkexdtk

4nkexdtk2#

就我个人而言,我会这样做:

public function run()
{

    $videos = factory(Video::class, 10000)->make();

    $chunks = $videos->chunk(2000);
    
    $chunks->each(function ($chunk) {
        Video::insert($chunk->toArray());
    });
}

通常快得多,与faker的使用无关

相关问题