Eloquent is sorting my results on its own - laravel

I was grouping the orders data for a graph and used the following eloquent query to achieve that,
Order::selectRaw("CONCAT(monthname(created_at),'-',year(created_at)) as date, count(id) as orders")
->groupBy('date')->get();
I got the expected results on my local machine where dates were in normal order, but when running the same thing on production. I get the following output:
Illuminate\Database\Eloquent\Collection {#4607
all: [
App\Order {#4564
date: "April-2020",
orders: 1,
},
App\Order {#4571
date: "August-2019",
orders: 4,
},
App\Order {#4611
date: "December-2019",
orders: 14,
},
App\Order {#4570
date: "February-2020",
orders: 2,
},
App\Order {#4582
date: "January-2020",
orders: 8,
},
App\Order {#4613
date: "June-2020",
orders: 1,
},
App\Order {#4565
date: "March-2020",
orders: 8,
},
App\Order {#4610
date: "May-2020",
orders: 10,
},
App\Order {#4588
date: "November-2019",
orders: 15,
},
App\Order {#4599
date: "October-2019",
orders: 8,
},
App\Order {#4600
date: "September-2019",
orders: 11,
},
],
}
It seems to be sorted in alphabetical order but I cannot figure out why. Can anyone tell me what could be the issue?
And yes on my local I use SQL ver 8, and on prod we use SQL 5, could that be the cause? How would I fix that?

you can order the results output by simply sticking with the raw expression and adding it in the groupBy() as well...
So change this...
->groupBy('date')
To this...
->groupBy(\DB::raw("CONCAT(monthname(created_at),'-',year(created_at)))")
Order::selectRaw("CONCAT(monthname(created_at),'-',year(created_at)) as date, count(id) as orders")
->groupBy(\DB::raw("CONCAT(monthname(created_at),'-',year(created_at)))")->get();
I hope this helps you.
This is what helped me lol...
https://laraveldaily.com/eloquent-trick-group-by-raw-with-boolean-condition/

to get riddle of automatic and non-automatic sort, just sort it your self:
first: go to config\database.php and make mysql non-strict:
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
----------
'strict' => true, // change it to false
then make your query like:
Order::selectRaw("created_at,CONCAT(monthname(created_at),'-',year(created_at)) as date,
count(id) as orders")->orderBy("created_at")
->groupByRaw('date')->get();

Related

using pluck on nested results in Laravel

I have a query that returns the following results.
Illuminate\Database\Eloquent\Collection {#5145
all: [
App\Models\Result {#5207
id: 198,
result_id: 30,
result_type: "App\Models\Touchpoint",
audit_id: 1,
weight: 7,
pics: 0,
recs: 0,
rating: 4,
comments: "none",
complete: 1,
created_at: "2022-06-03 03:42:24",updated_at: "2022-06-03 03:42:24",
result: App\Models\Touchpoint {#5210
id: 30,
name: "Lineman",
description: "The location food offer was available on Lineman",
sort_order: 25,
req_pics: 0,
req_recs: 0,
sector_id: 1,
created_at: null,
updated_at: "2022-04-02 14:02:34",
},
},
App\Models\Result {#5119
id: 199,
result_id: 29,
result_type: "App\Models\Touchpoint",
audit_id: 1,
weight: 7,
pics: 0,
recs: 0,
rating: 4,
comments: "none",
complete: 1,
created_at: "2022-06-03 03:43:38",
updated_at: "2022-06-03 03:43:38",
result: App\Models\Touchpoint {#5206
id: 29,
name: "Grab",
description: "The location food offer was available on Grab",
sort_order: 24,
req_pics: 0,
req_recs: 0,
sector_id: 1,
created_at: null,
updated_at: "2022-04-02 14:02:26",
},
},
],
}
This is the query I'm using to get that collection and I want the result to just contain sort_order, name, description, rating and weight from these results and place them in an array. I'm assuming I need to use pluck to get the correct fields but when I try to pluck 'result.name', etc. I get told result doesn't exist.
$result = Result::query()->where('audit_id', 1)->where('result_type', 'App\Models\Touchpoint')->whereIn('result_id', $tps)->with('result')->get();
This needs to be in a query without manipulating the collection as I need to feed it into Maatwebsite\Excel\Concerns\WithMultipleSheets, which requires a query not the query results.
You can use eager load constraints
$result = Result::query()
->where('audit_id', 1)
->where('result_type', 'App\Models\Touchpoint')
->whereIn('result_id', $tps)
->with('result:id,sort_order,name,description')
->select('id', 'result_id', 'rating', 'weight')
->get();
If you want to remove the nesting and flatten the result set you can map() over the collection
$result->map(function($item) {
$item['sort_order'] = $item->result->sort_order;
$item['name'] = $item->result->name;
$item['description'] = $item->result->description;
//remove the nested relation
$item->unsetRelation('result');
})
->toArray();
/**
* Will return something like
[
[
'id' => 198,
'result_id' => 30,
'rating' => 4,
'weight' => 7,
'sort_order' => 25,
'name' => 'Lineman',
'description' => 'The location food offer was available on Lineman'
],
[
'id' => 199,
'result_id' => 29,
'rating' => 4,
'weight' => 7,
'sort_order' => 24,
'name' => 'Grab',
'description' => 'The location food offer was available on Grab'
]
]
*/
Laravel Docs - Eloquent Relationships - Constraining Eager Loads

Rxjs array of object distinct with clause

I've got these streams
const site = of([
{ name: 'Joe', age: 30, tsUpdate: 5 },
{ name: 'Frank', age: 20, tsUpdate: 4 },
{ name: 'Ryan', age: 50, tsUpdate: 4 }
]);
const db = of([
{ name: 'Jonas', age: 30, tsUpdate: 4 },
{ name: 'Frank', age: 21, tsUpdate: 8 },
{ name: 'Calgor', age: 50, tsUpdate: 4 },
{ name: 'Joe', age: 30, tsUpdate: 4 },
]);
The goal is to have a single array with distinct value for
name but with the highest tsUpdate
So for instance
{ name: 'Joe', age: 30, tsUpdate: 5 }
{ name: 'Joe', age: 30, tsUpdate: 4 }
I want
{ name: 'Joe', age: 30, tsUpdate: 5 }
I am able to have distinct value for name property
but I don't know how to pick the highest value for tsUpdate
https://stackblitz.com/edit/rxjs-mhept2?devtoolsheight=60
This could be a way to solve it:
forkJoin(
[
site,
db
]
).pipe (
map(([site, db]) => [...site, ...db]),
// Emit each item individually
mergeAll(),
// Group by their name
groupBy(o => o.name),
// For each separate group, find the object with the highest `tsUpdate`
mergeMap(
grp$ => grp$.pipe(
reduce((acc, crt) => crt.tsUpdate > acc.tsUpdate ? crt : acc),
),
),
// At the end, collect all the objects in an array
toArray(),
).subscribe(console.log);
A groupBy's group is a Subject, and that's why we can use mergeMap afterwards. That subject will emit whenever it finds an object that matches with its key.
StackBlitz.

How to use collection to merge arrays in laravel so that one becomes the key?

I have an array of arrays like so:
array (
array("Delhi", 22, "The capital of India"),
array("Varanasi", 23, "Oldest Living City"),
array ("Moscow", 24, "Capital of Russia"),
array ("Konya", 25, "The city of Rumi"),
array("Salzburg", 26, "The city of Mozart")
);
I want to make an associated collection like so:
['city' => "Delhi",
'id' => 22,
'description' => "The capital of India"
],
['city' => "Varanasi",
'id' => 23,
'description' => "Oldest Living City"
],
['city' => "Moscow",
'id' => 24,
'description' => "Captial of Russia"
]
This can be done by passing the data through a loop but is there anything in the collection that can get this done?
One could use array_combine or combine from Laravel
$collection = array(
array("Delhi", 22, "The capital of India"),
array("Varanasi", 23, "Oldest Living City"),
array("Moscow", 24, "Capital of Russia"),
array("Konya", 25, "The city of Rumi"),
array("Salzburg", 26, "The city of Mozart")
);
array_map(function($array){
return array_combine(['city', 'id', 'description'], $array);
}, $collection);
//Or with a Laravel collection
collect($collection)->map(function($arr){
return array_combine(['city', 'id', 'description'], $arr);
});

Datetime and numbers localization in adreportstats async query

Is there any way to set datetime and numbers format based on locale info in adreportstats asynchronous queries? I've tried to fetch data with request parameter "locale" but it fails.
UPD:
There is no code for this issue. I just want to get in response localized json data. Here is response example:
{
'data': [
{
'adgroup_id': 1,
'country': 'US',
'gender': 'female',
'date_start': 2013-09-01,
'date_stop': 2013-09-02,
'reach': 2000,
'ctr': 0.42333333333333
},
{
'adgroup_id': 2,
'country': 'UK',
'gender': 'male',
'date_start': 2013-09-01,
'date_stop': 2013-09-02,
'reach': 1500,
'ctr': 0.33333333333333
},
...
]}
I want to get it for "de_DE" locale:
{
'data': [
{
'adgroup_id': 1,
'country': 'US',
'gender': 'female',
'date_start': 01.09.2013, <------ de_DE localized date
'date_stop': 02.09.2013,
'reach': 2000,
'ctr': 0,42333333333333 <------ de_DE localized number
},
{
'adgroup_id': 2,
'country': 'UK',
'gender': 'male',
'date_start': 01.09.2013,
'date_stop': 02.09.2013,
'reach': 1500,
'ctr': 0,33333333333333
},
...
]}
By design: "The Ads API does not support the "locale" parameter. The supported parameters for Ad Report Stats are documented here: https://developers.facebook.com/docs/reference/ads-api/adreportstats/"

How to find out max or latest date? How to create Calculate fields? How to delete a field? - Rethinkdb

Below are the questions i have asked on github.com/rethinkdb issues which they have answered.
I am posting here for the benefit of rethinkdb community
1.How to filter max date from the below data:
[
{"TimeStamp": Fri Oct 11 2013 05:51:12 GMT+00:00},
{"TimeStamp": Thu Oct 10 2013 15:41:09 GMT+00:00},
{"TimeStamp": Thu Oct 10 2013 15:44:04 GMT+00:00}
]
2.How to create Calculated fields?I have data like this in rethinkdb
[
{id: 1, sales: 1000, discount: 0.1},
{id: 2, sales: 2000, discount: 0.2},
{id: 3, sales:3000, discount: 0.1}
]
How can i transform that as below:
[{id: 1, sales: 1000, discount: 0.1, discAmt: 100, netSales: 900},
{id: 2, sales: 2000, discount: 0.2, discAmt: 400, netSales: 1600},
{id: 3, sales: 3000, discount: 0.1, discAmt: 300, netSales: 2700}
]
How to delete discount field from the above?
1. Max Date
For the max timestamp, if you just want to retrieve the last timestamp, you can do
r.table("foo").map( r.row("TimeStamp") ).reduce( function(left, right) {
return r.branch( left.gt(right),
left,
right
})
If you want the document with the greatest timestamp, you can do
r.table("foo").orderBy(r.desc("TimeStamp")).limit(1)
This will sort the whole table, so you may want to create an index on TimeStamp and use
r.table("foo").orderBy({index: "TimeStamp"}).limit(1)
2.Calculated fields
r.db("books").table("sales").update( function(row){
var discAmt = row("sales").mul(row("discount"));
return {
discAmt: discAmt,
netSales: row("sales").sub(discAmt)
}
})
.run()
3.Deleting a field
r.db("books").table("sales").replace( function(row) {
return row.unpick("discount");
})
.run()
I hope this will help the rethinkdb starter's like me.
Thanks

Resources