updateOrCreate where date is greater than today - php

Is there a way to updateorcreate records in a table where the created_at date field is greater than today(midnight)?
I have the following sample:
Model::updateOrCreate(
[
'match_id' => $match->id,
// 'created_at' => some query here to match a record created today
]
);

Here's the solution I found to work:
Model::updateOrCreate(
[
'match_id' => $match->id,
'created_at' => Model::where('created_at', '>', DB::raw('CURDATE()'))->first()->created_at ?? null
],
[
'otherColumn' => $value
]
);

Related

Laravel 8.x - How to use updateOrCreate with a where clause?

I am trying to use Laravel updateOrCreate to update a record if its within this month and last month based on if an ID exists.
\App\Models\Result::updateOrCreate(
[
'id' => $request->get('id'),
// where created_at is within the last 2 months
'created_at' => [
'>',
\Carbon\Carbon::now()->startOfMonth()->subMonthsNoOverflow()
],
],
[
'discipline_one' => $request->get('d-one'),
'discipline_two' => $request->get('d-two'),
'discipline_three' => $request->get('d-three'),
'discipline_four' => $request->get('d-four'),
'discipline_five' => $request->get('d-five'),
'discipline_six' => $request->get('d-six'),
]
);
If the ID exists, and the result is in this current month or last, a new record is created instead of updated.
Expected input: 1 (which exists from last month)
Expected output: Record is updated
Expected input: 2 (which doesn't exist or is not within 2 months)
Expected output: New record is created
Update:
Using the answer suggested,
'id' => $request->get('id'),
'created_at' => \App\Models\Result::whereBetween('created_at', [
\Carbon\Carbon::now()->startOfMonth()->subMonthsNoOverflow(),
\Carbon\Carbon::now()->endOfMonth(),
]),
I get the error:
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string
Here you go:
You only need to explicitly define the operators in the method's first parameter.
Each element of the array in the method's first parameter should be an array containing the three arguments.
column, operator, value
$startDate = \Carbon\Carbon::now()->startOfMonth()->subMonths(2);
$endDate = \Carbon\Carbon::now()->endOfMonth();
$resultRow = \App\Models\Result::query()
->where('id', $request->id)
->whereBetween('created_at', [$startDate, $endDate])
->first();
\App\Models\Result::updateOrCreate(
[
[
'id', '=', $request->get('id'),
],
[
'created_at', '>=', $startDate,
],
[
'created_at', '<=', $endDate,
],
],
array_merge(
[
'discipline_one' => $request->get('d-one'),
'discipline_two' => $request->get('d-two'),
'discipline_three' => $request->get('d-three'),
'discipline_four' => $request->get('d-four'),
'discipline_five' => $request->get('d-five'),
'discipline_six' => $request->get('d-six'),
],
$resultRow ? [] : [
'id' => $request->get('id'),
'created_at' => \Carbon\Carbon::now()
]
)
);
Notice that I repeated id & created_at column settings in the method's second parameter. It's because contrary to the regular behaviour, a merge of the 2 method's parameter arrays wasn't performed based on my tests if no result was found with that criteria.

Laravel unique identifiers for latest foreign key in collection

I have a Laravel collection with record IDs and foreign keys:
{id=1, foreign_id=1},
{id=2, foreign_id=1},
{id=3, foreign_id=2},
{id=4, foreign_id=3},
{id=5, foreign_id=2}
I expect:
{id=2, foreign_id=1},
{id=5, foreign_id=2},
{id=4, foreign_id=3}
I want to search Laravel query builder for unique values ​​for foreign_id if id in collection occurs more than 1 time.
I want then to give latest foreign_id.
Try $collection->unique('foreign_id');
Here I'm giving an example, You can check by yours,
$a = collect([
[
'id' => 1,
'foreign_id' => 2
],
[
'id' => 2,
'foreign_id' => 1
],
[
'id' => 3,
'foreign_id' => 2
],
[
'id' => 4,
'foreign_id' => 3
],
[
'id' => 5,
'foreign_id' => 2
],
]);
$a->unique('foreign_id');
The easiest way to do it is to sort collection by "id" in descending order and than use unique method by "foreign_id"
$myCollection->sortByDesc('id')->unique('foreign_id')

How to filter elasticsearch by date field with date modification

To filter by date, I use the following queries:
'body' => [
'query' => [
'bool' => [
'filter' => [
'range' => [
'expire_at' => [
'gte' => now()
]
]
]
]
]
]
UPD: All records have another date field - last_checked. The question is how to select records in which, for example, (expire_at - 7 days) > last_checked?
Check the range query documentation: you can use date math in the range parameters. E.g., expire_at - 7 days < now() means that the expiration will be within the next 7 days. Then you can do:
"range": {
"expire_at": {
"lt": "now+7d/d"
}
}
Note that this will include also already expired items. If you want to avoid that, you can add the condition that the expiration date is not met yet:
"range": {
"expire_at": {
"lt": "now+7d/d",
"gte": "now/d"
}
}
use this code
"expire_at" => array(
"lt" => "now+7d/d"
)

Merging doc_count result from keyed buckets

I have a query like
'aggs' => [
'deadline' => [
'date_histogram' => [
'field' => 'deadline',
'interval' => 'month',
'keyed' => true,
'format' => 'MMM'
]
]
]
the result I am getting are buckets with keys as month names.
The problem I am facing is the buckets with the month names as keys for a previous year are over written by another month of the next year (because obviously the key is same).
I want results where doc-count of buckets of previous which are over written merge with the doc_count of the next.
You can either add a separate month field during indexing and perform aggregation on it or use below script
{
"size": 0,
"aggs": {
"deadline": {
"histogram": {
"script": { "inline" : "return doc['deadline'].value.getMonthOfYear()" },
"interval": 1
}
}
}
}
Creating a separate month field will have better performance
Replace the format from MMM to YYYY-MMM as below:
'aggs' => [
'deadline' => [
'date_histogram' => [
'field' => 'deadline',
'interval' => 'month',
'keyed' => true,
'format' => 'YYYY-MMM'
]
]
]
After this you can handle the merging process at your application level

Laravel 5 Eloquent sum of multiplied columns for mongo DB

This is my invoices mongo table
{
'_id': ObjectId("565d78336fe444611a8b4593"),
'TransactionID': 'X020',
'Type': 'SALESINVOICE',
'InvoiceNumber': 'ABC020',
'Date': '2015-11-01 00:00:00',
'DueDate': '2015-12-01 00:00:00',
'CurrencyCode': 'GBP',
'CurrencyRate': NumberLong(1.2),
'Total': NumberLong(200),
'PlannedPaymentDate': '',
'HasAttachments': 0,
'UpdatedDate': '2015-12-01 10:36:35',
'AmountDue': NumberLong(200),
'AmountPaid': 0,
'Status': 'OPEN',
'AmountCredited': 0,
'AmountDebited': 0,
'Source': 1,
'InvoiceID': 'csv_1_X020',
'ExpectedPaymentDate': '2015-12-01 00:00:00',
'ContactID': 1,
'ValidateStatus': 'IMPORT',
'StatusChangeDate': ''
}
What i want the multiplication of two fields (Total * CurrencyRate)
I tried this query ::
DB::connection($this->MongoSchemaName)->collection($this->InvoicesTable)->where('Type', 'PAYMENT')->where('ContactID', (int)$customer->ContactID)->select(DB::raw('sum(Total*CurrencyRate)'))->first();
and tried more ::
DB::connection($this->MongoSchemaName)->collection($this->InvoicesTable)->where('Type', 'PAYMENT')->where('ContactID', (int)$customer->ContactID)->sum(DB::raw('Total * CurrencyRate'));
but not getting the exact out put all time i get 0
I believe aggregation operators like sum expect exact column name as a parameter. You can try to project the multiplication first, then sum the result:
DB::connection($this->MongoSchemaName)
->collection($this->InvoicesTable)
->where('ContactID', (int)$customer->ContactID)
->project([
'ContactID' => 1,
'TotalInBaseCurrency' => ['$multiply' => ['$Total', '$CurrencyRate']]
])
->sum('TotalInBaseCurrency')
or use aggregation directly:
DB::connection($this->MongoSchemaName)
->collection($this->InvoicesTable)
->raw(function($collection) use ($customer){
return $collection->aggregate([
['$match' => [
'ContactID' => (int)$customer->ContactID,
'Type' => 'PAYMENT'
]
],
['$group' => [
'_id' => '$ContactID',
'TotalInBaseCurrency' => [
'$sum' => ['$multiply' => ['$Total', '$CurrencyRate']]
]
]
]
]);
})

Categories