how can insert 1000000 row from textarea into database in laravel 8 ???????
i write this code and just can insert 30000 row and then browser give me HTTP ERROR 500
i set max_execution_time to 300 in php.ini
this is my code
please help me . thanks
public function mobile_store(Request $request)
{
$data = $request->validate([
'mobile' => ['required', 'string', 'unique:mobiles,mobile'],
]);
$textAr = collect(explode("\r\n", $data['mobile']));
$ALL = $textAr->unique();
$Filter = $ALL->filter()->all();
$counter_unique = count($Filter);
$counter = count($textAr);
$insert_data = collect();
foreach ($Filter as $line) {
if (strlen($line) >= 10) {
$final = '+98' . substr($line, -10);
}
$insert_data->push([
'mobile' => $final,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
}
foreach ($insert_data->chunk(5000) as $chunk) {
Mobile::insert($chunk->toArray());
}
return redirect()->back()->with('success', "There were $counter_unique rows in the list and $counter non-duplicate rows were entered");
}
Don't store all of the data first, just use 1 foreach and every 5000 records store the data and then reset the array and do the next batch of records.
$insert_data = collect();
$totalRecords = 0;
$batchCount = 0;
foreach ($Filter as $line) {
if (strlen($line) >= 10) {
$final = '+98' . substr($line, -10);
}
$insert_data->push([
'mobile' => $final,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
if ( $batchCount++ == 5000 ) {
// Insert data
Mobile::insert($insert_data->toArray());
// Reset batch collection
$insert_data = collect();
// Reset counter of current batch
$batchCount = 0;
}
// Count of all records
$totalRecords++;
}
// Insert remaining records
if( $insert_data->count() > 0 )
Mobile::insert($insert_data->toArray());
}
Related
When I try to push an array of records to my Laravel Collection, I end up with only the first record being inserted into the collection. It was working well before I made a few changes (related to $limit and $test) but now produces this bug.
public static function processOldOrders(int $limit = 1, bool $test = true)
{
//Read CSV and turn into a collection
$allOldOrders = Excel::toArray([], 'orders.csv');
$orderCollection = collect();
$count = 0;
foreach ($allOldOrders as $key => $oldOrder) {
$orderCollection->push(
(object) [
'order_id' => ltrim($oldOrder[$key][0], "#"),
'order_created' => $oldOrder[$key][4],
'email' => $test ? 'test#test.com' : trim(strtolower($oldOrder[$key][5])),
'phone' => ltrim($oldOrder[$key][12], "'"),
'first_name' => $oldOrder[$key][7],
'last_name' => $oldOrder[$key][8],
'purchase_status' => 'a_purchase',
'total_price' => $oldOrder[$key][33],
'items' => [],
'gift_cards' => [],
'coupons' => [],
'shipping_data' => [],
]
);
$count++;
if ($count >= $limit) {
break;
}
}
dd($orderCollection);
In your processOldOrders method by default you set limit = 1. And on the bottom,
$count = 0;
foreach ($allOldOrders as $key => $oldOrder) {
...
$count++;
if ($count >= $limit) {
break;
}
...
there you check it with count. At first time $count is equal to 0, and you plus it 1. Then you checking it with $limit. By default limit is 1 . So it works only one time. Yu have to more than one limit where you call processOldOrders method
There's nothing wrong with your code. But you forgot the output of Excel::toArray(), that it has sub-arrays.
array:1 [
0 => array [ // <-- init
0 => array [ // <-- CSV data
...
So, you can change your $allOldOrders to $allOldOrders[0] :
foreach ($allOldOrders[0] as $key => $oldOrder) {
...
}
In Laravel 8 / PHP 8, I receive a body in POST, transform the data, and bulk insert into TimescaleDB.
Here is the code:
public function store(Request $request)
{
ini_set('max_execution_time', -1);
$body = $request->getContent();
$meter = json_decode($body, true);
$chunkSize = 1000;
$measures = $meter['Measures'];
$chunkedRaws = collect($measures)->chunk($chunkSize);
$ok = 0;
$nok = 0;
$initialTime = Carbon::now();
foreach ($chunkedRaws as $chunkNumber => $raws) {
$chunkTime = Carbon::now();
$rawsToInsert = [];
foreach ($raws as $k => $raw) {
$rawTime = Carbon::now();
array_push($rawsToInsert, new \App\Models\Raw([
'operation_id' => $meter['OperationID'],
'meter_id' => $meter['ID'],
'conso_prod' => $meter['ConsoProd'],
'timestep' => $meter['Timestep'],
'unit' => $meter['Unit'],
'source' => $source,
'time' => Carbon::parse($raw['t'])->toIso8601ZuluString(),
'delta' => $raw['d'],
]));
}
// Insert into TimescaleDB cut
}
return response()->json(['message' => $ok . " Raws has been inserted,\n " . $nok . " Failed"], 200);
}
The first time I call it, I have a body with 3744 elements.
It will take aprox 5-6ms for each element to push into the array so, 6 x 3744 / 1000 = 22 sec aprox.
But my second post has 26930 elements. Now, each array_push will take aprox 52 ms, so 52 * 26930 / 1000 = 23 minutes aprox. Way to long.
the array_push should always be the same independently of how many rows there is in body ?
Why is the time spent on array_push proportional to the $chunkedRaws size ???
You can try to declare the object externally.
And as suggested above, you can stop using array_push
...
$raw = new \App\Models\Raw([
'operation_id' => $meter['OperationID'],
'meter_id' => $meter['ID'],
'conso_prod' => $meter['ConsoProd'],
'timestep' => $meter['Timestep'],
'unit' => $meter['Unit'],
'source' => $source,
]);
foreach ($chunkedRaws as $chunkNumber => $raws) {
$chunkTime = Carbon::now();
$rawsToInsert = [];
foreach ($raws as $k => $raw) {
$rawTime = Carbon::now();
// Here I'm assuming you have setter in your Raw object
$raw->setTime(Carbon::parse($raw['t'])->toIso8601ZuluString());
$raw->setDelta($raw['d']);
$rawsToInsert[] = $raw;
}
// Insert into TimescaleDB cut
}
...
i looping 2 array a date and the data
$rdate = $request->month; //<-- Requested month
$days = Carbon::create();
$days = $days->daysInMonth; //<-- Finding how much days in month
for ($i = 1; $i < $days; $i++) { //Looping Date
$date = $rdate . '-' . $i; //Making full Date with formate 'Y-m-d'
foreach ($games as $game) { //Looping game array have 3 collection ['game1', 'game2', 'game3']
$result = Result::whereDate('created_at', $date)->where('game', $game->name)->where('admin_id', $admin->id)->first(); // Query Results for getting perticular game with date
if ($result) { //Checking if current date haven't result
$r[] = [
'game' => $game->name,
'number' => $result->number
];
} else {
$r[] = [
'game' => $game->name,
'number' => '-'
];
}
}
$resultd[] = [
'date' => $date,
'results' => $r // i want to stop adding old data here
];
}
i am expecting this result
{"results":[{"date":"2020-08-1","results":[{"game":"game1","number":"-"},{"game":"game2","number":"-"},{"game":"game3","number":"-"}]},{"date":"2020-08-2","results":[{"game":"game1","number":"-"},{"game":"game2","number":"-"},{"game":"game3","number":"-"}]
What actually getting
Adding old $r to results array
How to fix it i am trying to break it but can't figure it out
I have some untested code, as I do not have your data but I think this code below should work, you may need to modify some code as needed.
$rdate = '2020-8';
$days = collect([1,2,3]);
$games = collect(['game1', 'game2', 'game3']);
return $days->map(function ($item) use ($rdate,$games) {
$date = $rdate.'-'.$item;
return [
"date" => $date,
"results" => $games->map(function ($g) use ($date) {
$result = Result::whereDate('created_at', $date)
->where('game', $g->name)
->where('admin_id', $admin->id)
->first();
return ['game' => $g->name,
'number' => $result ? $result->number : '-',
];
})
];
});
I think I'm close with my code but I am trying to get the count() from the array provided... total users and OS
$users = array();
if ($results = $dbh->runQuery($sql)) {
foreach ($results as $key=>$row){
$users[$row['user_id']][] = array('user_id'=>$row['user_id'],
'email' => $row['email'],
'last_login' => $row['last_login'],
'fname' => $row['fname'],
'lname' => $row['lname'],
'role_id' => $row['role_id'],
'role_name' => $row['role_name'],
'os_d_token' => $row['os'],
'roid_d_token' => $row['roid'],
'p_name' => $row['p_name']);
}
}
Get total count of users
$user_cnt = count($row['user_id']);
Get total count of users with OS
$total_os = '';
if($row['os'] != null || '-1') {
$total_os = count($row['os']);
}
count does not retain a counter for you. It immediately returns the number of items in an array. Since you're already looping, set counter variables:
$total = 0;
$total_os = 0;
foreach ($results as $key=>$row) {
$total++;
if ($row['os'] != null || $row['os'] != '-1') {
$total_os++;
}
...
}
Hi all I'm trying to insert multiple records using an api into a table. But I'm getting error like "Error connecting to database". How can i resolve it.
Below is my code
public function addToCart(){
$input = Input::all();
$data['status'] = 0;
$data['error'] = true;
if(isset($input['user_id']) && array_filter($input['cart']) > 0 ){
foreach($input['cart'] as $key => $val){
if(!empty($val['quantity']) && !empty($val['price']) && !empty($val['sku']) && !empty($val['qrcode']) && !empty($val['product_id']))
{
$totalPrice = $val['quantity']* $val['price'];
$cartId = DB::table('jocom_cart')->insertGetId(array(
'user_id' => $input['user_id'],
'product_id' => $val->product_id,
'sku' => $val->sku,
'quantity' => $val->quantity,
'price' => $val->price,
'total_price' => $totalPrice,
'qrcode' => $val->qrcode
)
);
}
else{
$data['message'] = 'All field are required.';
}
return Response::json($data);
}
Create one array of the data and then pass the array to insert function
try to avoid query in the loop
$insertRecord = [];
foreach($input['cart'] as $key => $val){
if(!empty($val['quantity']) && !empty($val['price']) && !empty($val['sku']) && !empty($val['qrcode']) && !empty($val['product_id']))
{
$totalPrice = $val['quantity']* $val['price'];
$insertRecord[$key] = ['user_id'=>$input['user_id'],'product_id' => $val->product_id,... ,... ,...]; All your column with value
}
}
if(!empty($insertRecord)){
Model::insert($insertRecord); // Eloquent approach
DB::table('table')->insert($insertRecord); // Query Builder approach
}
Your record should be in array.
Table::insert(Array)