i am trying to preform update or create action on many records using laravel model.
Normal insert with updateOrCreate works perfectly with foreach but i want to avoide it as it slowing things down.
I have something like 200k records.
Is there is any way to achive it?
I tried this answer below
https://stackoverflow.com/a/34815725/1239122
But it is not super elegant.
Any ideas?
You can try this library for batch insert and update.
https://github.com/mavinoo/laravelBatch
I didn't find a way to bulk insert or update in one query. But I have managed with only 3 queries. I have one table name shipping_costs. Here I want to update the shipping cost against the shipping area. I have only 5 columns in this table id, area_id, cost, created_at, updated_at.
// first get ids from table
$exist_ids = DB::table('shipping_costs')->pluck('area_id')->toArray();
// get requested ids
$requested_ids = $request->get('area_ids');
// get updatable ids
$updatable_ids = array_values(array_intersect($exist_ids, $requested_ids));
// get insertable ids
$insertable_ids = array_values(array_diff($requested_ids, $exist_ids));
// prepare data for insert
$data = collect();
foreach ($insertable_ids as $id) {
$data->push([
'area_id' => $id,
'cost' => $request->get('cost'),
'created_at' => now(),
'updated_at' => now()
]);
}
DB::table('shipping_costs')->insert($data->toArray());
// prepare for update
DB::table('shipping_costs')
->whereIn('area_id', $updatable_ids)
->update([
'cost' => $request->get('cost'),
'updated_at' => now()
]);
You can use insert() in Query Builder to bulk insert. But update statement needs conditions. Please read the document:
https://laravel.com/docs/5.7/eloquent#updates
As far as I know, you can not do it for the update as you need to check the condition for the update, But you can do it for insert
$data = array(
array('name'=>'John', 'phone'=>'1234567890'),
array('name'=>'Deo', 'phone'=>'9876543210'),
//...
);
Model::insert($data);
Related
I am performing a database operation with "Eloquent ORM in Laravel". I just want to take the last insert id (not the maximum id) in the database.
I searched to get last insert id in laravel Eloquent ORM, I got following link (Laravel, get last insert id using Eloquent) that is refer to get last insert id from following function "$data->save()".
But I need to get
"Model::insert($data)";
My Query:
$insert = Product::insert($alldata);
if ($insert) {
return response()->json([
'success' => 'Ürün başarıyla Eklendi.',
'id' => ???????
]);
}
How can I retrieve the last inserted id?
$insert = Product::create($alldata);
$insert->id
Holds the id of the inserted item.
Basically you have the whole collection in your $insert variable, of the item that you inserted.
You can Also Use insertGetId() function
$id = DB::table('table_name')-> insertGetId($alldata);
How do I can select data to show based on comparation in yii2 Activerecord? My data record from db contain column depTime. So I want to show only data that has depTime less than current time.
Here is my function in my controller.
public function actionSelectedTeam($id) {
$searchModel = new TeamSearch();
$dataProvider= $searchModel->search(Yii::$app->request->queryParams);
$dataProvider->pagination = [
'pageSize' => 5
];
return $this->render('team-info', [
'model' => $this->findModel($id),
'dataProvider' => $dataProvider,
]);
}
Or there is another way to do that? I mean outside this method, maybe from the model.
Thankyou.
You will always have the records displayed that are smaller than the current time, other than they are some kind of reservations and you are providing future date/time manually.
You haven't specified what is the type of the depTime column, I assume that you have a datetime column, you can use the time() and now() function to achieve this.
You can add the following line in your search model's search() method before you return the $dataProvider which is subtracting the depTime from the current time and if the result is positive it will include the record.
$query->andFilterWhere(['>', new Expression('time(now()) - time(depTime)'), 0]);
I have two models : Event and Soundcloud.
Both are defined to be a many-to-many relationship in Laravel and it is working fine.
I am saving the soundcloud and population the pivot table event_soundcloud by doing this
foreach ($data as $artist => $url) {
$soundcloud = Soundcloud::firstOrNew(['artist_name' => $artist, 'link' => $url]);
$event->soundclouds()->save($soundcloud);
}
That function is called every 10 minutes and each time the same records are added to the pivot table.
Is there a way to do the same thing but adding records in pivot table only if it does not exist already ?
Thank you
Here is what I did to make it work. I guess you cannot do it in one step
$soundcloud = Soundcloud::firstOrNew(['artist_name' => $artist, 'link' => $url]);
$soundcloud->save();
$event->soundclouds()->sync([$soundcloud->id], false);
I have a problem with updated_at, created_at fields in Laravel 5.
Here is my migration:
Schema::create('lots', function (Blueprint $table) {
$table->increments('id');
$table->integer('lot');
$table->integer('is_active');
$table->timestamps();
});
But when I insert some data into this table, updated_at and created_at fields are null. How make them auto-complete with current timestamps?
I insert data like this:
\DB::table('admin_lots')->insert([
'lot' => $request->cycle_lot,
'is_active' => '1',
]);
Thanks.
You have to use the create method instead of the insert method in Laravel.
The create method automatically adds timestamps for created_at and updated_at fields:
// GOOD:
User::create(array(
'name' => 'John'
));
On the contrary, the insert method bypasses Eloquent, (it uses the query builder) and does not update updated_at/created_at columns!
// BAD:
User::insert([
'name' => '[[ test name ]]',
]);
dd(
User::where(['name' => '[[ test name ]]'])->first()->create_date
);
You probably do not use Eloquent when inserting data, in this case you should add timestamps manually.
If you do not want to do this, but you still need filled timestamps, use this hack:
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
Update
Based on your updated code, here's another solution:
\DB::table('admin_lots')->insert([
'lot' => $request->cycle_lot,
'is_active' => '1',
'created_at' = \Carbon\Carbon::now()->toDateTimeString(),
'updated_at' = \Carbon\Carbon::now()->toDateTimeString()
]);
Check if your model has this line.
public $timestamps = false;
If it has, delete it.
When you instert data directly, Laravel won't know about your timestamps.
You can either set the timestamps manually in the insert statement, or switch to using Eloquent models , which handle many things out of the box for you, including timestamps. It's also way easier to maintain than straight queries, where applicable.
Eloquent ORM
You need to use Laravel's awesome Eloquent feature to make timestamps written to the Database automatically...
As by seeing your example the code for eloquent will go something like this:
$lot_inputs = array(
'lot' => $request->cycle_lot,
'is_active' => 1
);
$new_lot = Lot::create($lot_inputs);
Please note that you should have the Model for the table = 'lots' (and it must extend Eloquent) so that you can easily use Eloquent methods and its properties...
It would be great if you use Eloquent ORM as much as possible so that if in future you want to change your DB technology then you won't need to specify the written eloquent queries again (e.g: the conversion of query to different DB languages is automatically done by Eloquent)
Thanks I hope this will help you to resolve your issue..!!
I'm having trouble getting a chained query to work for deleting a single record in 2 different columns in the user model. On submit, I want to delete the user's record in column A and column B only, nothing else.
DB::table('users')
->where('id', Auth::user()->id)
->select('column_A')->delete()
->select('column_B')->delete()
->update([
'column_A' => 'value',
]);
This actually deletes that user's entire record. I have also tried substituting select for value and then I'll get the error:
calling delete() on string
Thanks!
Try something like this:
DB::table('users')
->where('id', Auth::user()->id)
->update([
'column_A' => '',
'column_B' => ''
]);
I can use delete() only to delete whole rows, but not some information in that row.