Skip to content

Commit

Permalink
Merge pull request #55 from mrmmg/bulk-insert-queries
Browse files Browse the repository at this point in the history
Bulk insert queries
  • Loading branch information
nnjeim authored May 30, 2023
2 parents 143de03 + 6df9069 commit d5d7636
Showing 1 changed file with 100 additions and 41 deletions.
141 changes: 100 additions & 41 deletions src/Actions/SeedAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace Nnjeim\World\Actions;

use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Nnjeim\World\Models;
use Illuminate\Database\Seeder;
Expand Down Expand Up @@ -161,56 +163,87 @@ private function seedStates(Models\Country $country, array $countryArray): void

$this->forgetFields($stateFields, ['id', 'country_id']);

foreach (array_chunk($countryStates, 20) as $stateChunks) {
$bulk_states = [];

foreach ($stateChunks as $stateArray) {
foreach ($countryStates as $stateArray) {

$stateArray = array_map(fn ($field) => gettype($field) === 'string' ? trim($field) : $field, $stateArray);
$stateArray = array_map(fn ($field) => gettype($field) === 'string' ? trim($field) : $field, $stateArray);

$state = $country
->states()
->create(Arr::only($stateArray, $stateFields));
// state cities
if ($this->isModuleEnabled('cities')) {
$stateCities = Arr::where(
$this->modules['cities']['data'],
fn ($city) => $city['country_id'] === $countryArray['id'] && $city['state_id'] === $stateArray['id']
);
$bulk_states[] = Arr::add(
Arr::only($stateArray, $stateFields),
'country_id',
$country->id
);
}

$this->seedCities($country, $state, $stateCities);
}
}
}
DB::beginTransaction();

try {
$last_state_id_before_insert = $this->findLastStateIdBeforeInsert();

Models\State::query()
->insert($bulk_states);

$bulk_states = $this->addStateIdAfterInsert($bulk_states, $last_state_id_before_insert);

//state cities
if ($this->isModuleEnabled('cities')) {
$stateNames = array_column($bulk_states, 'name');

$stateCities = Arr::where(
$this->modules['cities']['data'],
fn ($city) => $city['country_id'] === $countryArray['id'] && in_array($city['state_name'], $stateNames, true)
);

$this->seedCities($country, $bulk_states, $stateCities);
}
} catch (Exception $exception){
throw $exception;
} finally {
DB::commit();
}
}

/**
* @param Models\Country $country
* @param Models\State $state
* @param array $states
* @param array $cities
*/
private function seedCities(Models\Country $country, Models\State $state, array $cities): void
private function seedCities(Models\Country $country, array $states, array $cities): void
{
// state schema
// city schema
$cityFields = Schema::getColumnListing(config('world.migrations.cities.table_name'));

$this->forgetFields($cityFields, ['id', 'country_id', 'state_id']);

foreach (array_chunk($cities, 20) as $cityChunks) {
//using array_chunk to prevent mySQL too many placeholders error
foreach (array_chunk($cities, 500) as $cityChunks) {
$cities_bulk = [];
foreach ($cityChunks as $cityArray) {
$cityArray = array_map(fn ($field) => gettype($field) === 'string' ? trim($field) : $field, $cityArray);

foreach ($cityChunks as $cityArray) {
$city = Arr::only($cityArray, $cityFields);

$cityArray = array_map(fn ($field) => gettype($field) === 'string' ? trim($field) : $field, $cityArray);
$state = Arr::first($states, fn($state) => $state['name'] === $cityArray['state_name']);

$country
->cities()
->create(
array_merge(
Arr::only($cityArray, $cityFields),
['state_id' => $state->id]
)
);
}
}
$city = Arr::add(
$city,
'state_id',
$state['id']
);

$city = Arr::add(
$city,
'country_id',
$country->id
);

$cities_bulk[] = $city;
}

Models\City::query()
->insert($cities_bulk);
}
}

/**
Expand All @@ -220,13 +253,17 @@ private function seedCities(Models\Country $country, Models\State $state, array
*/
private function seedTimezones(Models\Country $country, $countryArray): void
{
$bulk_timezones = [];

foreach ($countryArray['timezones'] as $timezone) {
$country
->timezones()
->create([
'name' => (string) $timezone['zoneName'],
]);
$bulk_timezones[] = [
'country_id' => $country->id,
'name' => (string) $timezone['zoneName']
];
}

Models\Timezone::query()
->insert($bulk_timezones);
}

private function seedCurrencies(Models\Country $country, array $countryArray): void
Expand Down Expand Up @@ -258,10 +295,9 @@ private function seedCurrencies(Models\Country $country, array $countryArray): v
*/
private function seedLanguages(): void
{
// languages
foreach ($this->modules['languages']['data'] as $language) {
Models\Language::create($language);
}
// languages
Models\Language::query()
->insert($this->modules['languages']['data']);
}

/**
Expand All @@ -277,4 +313,27 @@ private function forgetFields(array &$array, array $values)
}
}
}

private function findLastStateIdBeforeInsert()
{
$state = Models\State::query()->orderByDesc('id')->first();

$last_state_id_before_insert = 0;

if (!is_null($state)) {
$last_state_id_before_insert = $state->id;
}

return $last_state_id_before_insert;
}

private function addStateIdAfterInsert(array $bulk_states, $last_state_id_before_insert)
{
$count = count($bulk_states);

for ($i = 1; $i <= $count; $i++) {
$bulk_states[$i - 1]['id'] = $last_state_id_before_insert + $i;
}
return $bulk_states;
}
}

0 comments on commit d5d7636

Please sign in to comment.