GroupBy nested multiple levels in Laravel - laravel

I have a list of nested multi level objects.
This is from eloquent query with relationship.
A Place has many Orders
An Order has many Details and one Customer
A Detail has one product and one deliver Period
[
{
"place_id": 1,
"name": "A Building",
"address": "A Street, A Ward, A City",
"orders": [
{
"customer": {
"id": 1,
"name": "Peter",
"phone": "011111111"
},
"order_details": [
{
"period_id": 1,
"period": {
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00"
},
"product_id": 1,
"product": {
"name": "A Cup of Tea"
}
}
]
},
{
"customer": {
"id": 2,
"name": "Mary",
"phone": "022222222222"
},
"order_details": [
{
"period_id": 1,
"period": {
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00"
},
"product_id": 3,
"product": {
"name": "Glass of Milk Shake"
}
}
]
}
]
},
{
"place_id": 2,
"name": "B Building",
"address": "B Street, B Ward, B City",
"orders": [
{
"customer": {
"id": 3,
"name": "Catherine",
"phone": "0333333333"
},
"order_details": [
{
"period_id": 1,
"period": {
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00"
},
"product_id": 2,
"product": {
"name": "A Cup of Coffee"
}
}
]
},
{
"customer": {
"id": 4,
"name": "Tom",
"phone": "04444444444444"
},
"order_details": [
{
"period_id": 2,
"period": {
"id": 1,
"start_time": "10:00:00",
"end_time": "10:30:00"
},
"product_id": 1,
"product": {
"name": "A Cup of Tea"
}
}
]
}
]
}
]
I need group this list by "period" then "place"
Expect result:
[
{
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00",
"places": [
{
"place_id": 1,
"name": "A Building",
"address": "A Street, A Ward, A City",
"orders": [
{
"customer": {
"id": 1,
"name": "Peter",
"phone": "011111111"
},
"order_details": [
{
"period_id": 1,
"period": {
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00"
},
"product_id": 1,
"product": {
"name": "A Cup of Tea"
}
}
]
},
{
"customer": {
"id": 2,
"name": "Mary",
"phone": "022222222222"
},
"order_details": [
{
"period_id": 1,
"period": {
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00"
},
"product_id": 3,
"product": {
"name": "Glass of Milk Shake"
}
}
]
}
]
},
{
"place_id": 2,
"name": "B Building",
"address": "B Street, B Ward, B City",
"orders": [
{
"customer": {
"id": 3,
"name": "Catherine",
"phone": "0333333333"
},
"order_details": [
{
"period_id": 1,
"period": {
"id": 1,
"start_time": "08:00:00",
"end_time": "08:30:00"
},
"product_id": 2,
"product": {
"name": "A Cup of Coffee"
}
}
]
}
]
}
]
},
{
"id": 2,
"start_time": "10:00:00",
"end_time": "10:30:00",
"places": [
{
"place_id": 2,
"name": "B Building",
"address": "B Street, B Ward, B City",
"orders": [
{
"customer": {
"id": 4,
"name": "Tom",
"phone": "04444444444444"
},
"order_details": [
{
"period_id": 2,
"period": {
"id": 1,
"start_time": "10:00:00",
"end_time": "10:30:00"
},
"product_id": 1,
"product": {
"name": "A Cup of Tea"
}
}
]
}
]
}
]
}
]
Here is my detail code :
class Place extends Model
{
public function orderDetails()
{
return $this->hasManyThrough(OrderDetail::class,
Order::class,'place_id','order_id','id','id');
}
}
class Period extends Model
{
public function details()
{
return $this->hasMany(OrderDetail::class, 'period_id', 'id');
}
}
class Order extends Model
{
public function place()
{
return $this->belongsTo(Place::class, 'place_id', 'id');
}
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
public function details()
{
return $this->hasMany(OrderDetail::class, 'order_id', 'id');
}
}
class OrderDetail extends Model
{
public function period()
{
return $this->belongsTo(Period::class, 'period_id', 'id');
}
public function product()
{
return $this->belongsTo(Product::class, 'product_id', 'id');
}
public function order()
{
return $this->belongsTo(Order::class, 'order_id', 'id');
}
}
Place::with(['orderDetails', 'orderDetails.product', 'orderDetails.period', 'orderDetails.order.user'])->get()->toArray();
I m using laravel so better use collection helper of laravel to solve this faster.
Please help me . Thanks
Updated:
i used another query and group
In OrderDetail model add:
protected $appends = ['place_id'];
public function getPlaceIdAttribute()
{
return $this->order->place_id;
}
Then use this query i can group period than place but it 's only contain id.
OrderDetail::with(['order','order.user','order.place','product','period'])->get()->groupBy(['period_id','place_id'])->toArray();

I solved this .
OrderDetail::with(['order','order.user','order.place','product','period'])->get()->groupBy(['period.id','order.place.id'])->map(function ($periods) {
$period = $periods->first()->first()->period;
return [
"start_time" => $period->start_time,
"end_time" => $period->end_time,
"places" => $periods->map(function ($places) {
$place = $places->first()->place;
return [
"name" => $place->name,
"address" => $place->address,
"details" => $places->toArray()
];
})->toArray()
];
})->toArray();

Related

How to filter out only entries of an embedded list with elastic search?

I want to filter out only entries from a list "NestedRecords" inside each "Record" entry.
Let's say I have these Id's of nested records which should be returned:
nestedRecordsToBeReturned = [1,3]
This is the given table with records and nestedRecords inside each record:
{
"Records": [
{
"Record": "record1",
"NestedRecords": [
{
"id": 1,
"label": "l1"
},
{
"id": 2,
"label": "l2"
},
{
"id": 3,
"label": "l3"
},
{
"id": 4,
"label": "l4"
},
{
"id": 6,
"label": "l6"
}
]
},
{
"Record": "record2",
"Records": [
{
"id": 1,
"label": "l1"
},
{
"id": 2,
"label": "l2"
},
{
"id": 4,
"label": "l4"
},
{
"id": 7,
"label": "l7"
}
]
},
{
"Record": "record3",
"Records": [
{
"id": 2,
"label": "l2"
},
{
"id": 3,
"label": "l3"
},
{
"id": 9,
"label": "l9"
},
{
"id": 10,
"label": "l10"
}
]
}
]
}
This is what I want to be returned:
{
"Records": [
{
"Record": "record1",
"NestedRecords": [
{
"id": 1,
"label": "l1"
},
{
"id": 3,
"label": "l3"
},
]
},
{
"Record": "record2",
"Records": [
{
"id": 1,
"label": "l1"
},
]
},
{
"Record": "record3",
"Records": [
{
"id": 3,
"label": "l3"
},
]
}
]
}
How do I achieve this with an elastic query?
Is it even possible to filter a list which is embedded in a document?

Laravel Eloquent Nested Eager Load Apply Order By

Given this data:
{
"current_page": 1,
"data": [
{
"id": 1,
"delivery_id": 1,
"deliveries_sub": {
"first_delivery_date": "08/31/2022",
"delivery" {
"day": "Monday",
"location": {
"direction": "North"
}
}
}
},
{
"id": 2,
"delivery_id": 2,
"deliveries_sub": {
"first_delivery_date": "09/28/2022",
"delivery" {
"day": "Friday",
"location": {
"direction": "South"
}
}
}
},
{
"id": 3,
"delivery_id": 2,
"deliveries_sub": {
"first_delivery_date": "08/31/2022",
"delivery" {
"day": "Wednesday",
"location": {
"direction": "Northeast"
}
}
}
},
{
"id": 4,
"delivery_id": 3,
"deliveries_sub": {
"first_delivery_date": "09/02/2022",
"delivery" {
"day": "Tueday",
"location": {
"direction": "North"
}
}
}
}
],
"first_page_url": "http://localhost/mypage/list?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "http://localhost/mypage/list?page=1",
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://localhost/mypage/list?page=1",
"label": "1",
"active": true
},
{
"url": null,
"label": "Next »",
"active": false
}
],
"next_page_url": null,
"path": "http://localhost/mypage/list",
"per_page": 10,
"prev_page_url": null,
"to": 4,
"total": 4
}
I would like to sort it by the first_delivery_date. I have fetched this one using:
DeliveryDays::with('deliverySub.delivery.location')
->orderBy('deliverySub.first_delivery_date')
->paginate(10);
It seems that the orderBy clause is not working. I've also tried this approach:
DeliveryDays::with(['deliverySub' => function ($query) {
$query->orderBy('first_delivery_date');
}, 'deliverySub.delivery.location'])
->paginate(10);
But it also doesn't work. My desired result would be the sorted first_delivery_date data:
{
"current_page": 1,
"data": [
{
"id": 1,
"delivery_id": 1,
"deliveries_sub": {
"first_delivery_date": "08/31/2022",
"delivery" {
"day": "Monday",
"location": {
"direction": "North"
}
}
}
},
{
"id": 3,
"delivery_id": 2,
"deliveries_sub": {
"first_delivery_date": "08/31/2022",
"delivery" {
"day": "Wednesday",
"location": {
"direction": "Northeast"
}
}
}
},
{
"id": 4,
"delivery_id": 3,
"deliveries_sub": {
"first_delivery_date": "09/02/2022",
"delivery" {
"day": "Tueday",
"location": {
"direction": "North"
}
}
}
},
{
"id": 2,
"delivery_id": 2,
"deliveries_sub": {
"first_delivery_date": "09/28/2022",
"delivery" {
"day": "Friday",
"location": {
"direction": "South"
}
}
}
}
],
"first_page_url": "http://localhost/mypage/list?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "http://localhost/mypage/list?page=1",
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://localhost/mypage/list?page=1",
"label": "1",
"active": true
},
{
"url": null,
"label": "Next »",
"active": false
}
],
"next_page_url": null,
"path": "http://localhost/mypage/list",
"per_page": 10,
"prev_page_url": null,
"to": 4,
"total": 4
}
What would be the best approach for sorting the results? Is it within the eager load or after fetching the results? Thanks.
Try this
DeliveryDays::with(['deliverySub' => function($query){
$query->orderBy('first_delivery_date');
}, 'deliverySub.delivery.location'])->paginate(10);

How to groupBy the collection of Laravel with the nested field of type array?

I have this collection, and I want to change this data in order that the key will be the branches id and the value will be the items:
{
"data": [
{
"id": 5020,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
{
"id": 6,
"title": "vegetable",
},
},
{
"id": 5025,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
}
]
}
I want to group by this data by branches -> id , something like this:
{
"data": [
"7" : [
{
"id": 5020,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
{
"id": 6,
"title": "vegetable",
},
},
{
"id": 5025,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
]
}
],
"6" : [
{
"id": 5020,
"category_id": 577,
"branches": [
{
"id": 7,
"title": "water",
},
{
"id": 6,
"title": "vegetable",
},
},
],
}
How can I use the group By method of collection in Laravel? I want to have data like this and my data is the type of collection
You can use a callback in groupBy method to provide custom logic.
Example:
collect($data)->groupBy(fn($item, $key) => $item['branches'][0]['id']);
But in this example I want to suggest you to use loop:
$myGroups = [];
foreach($data as $item) {
foreach($item['branches'] as $branch) {
$myGroups[$branch['id']][] = $item;
}
}

How to use filter in map

I have following code:
%dw 2.0 output application/json var attributeIdMapping =
${vault::attributeIdMapping}
--- {
"objectTypeId": 3,
"attributes": vars.requestBody mapObject (value, key) ->
{
"objectTypeAttributeId": (attributeIdMapping.attributes filter ($.name == key))[0].id,
"objectAttributeValues": [{
"value": value,
"key": key
}]
} }
attributeIdMapping:
{
"attributes": [
{
"name": "accountType",
"id": "87"
},
{
"name": "accountClass",
"id": "89"
},
{
"name": "accountName",
"id": "85"
},
{
"name": "displayName",
"id": "18"
},
{
"name": "accountCategory",
"id": "88"
},
{
"name": "accountNumber",
"id": "84"
},
{
"name": "description",
"id": "86"
},
{
"name": "accountGroup",
"id": "90"
}
]
}
vars.requestBody:
{
"displayName": "TestMulesoft2",
"description": "Test"
}
But my filter shows null in the end. As I understand key is not passed to level below map itself. How can I get this working?
I put all the input data inside the script to simplify reproduction. The problem seems to be using the operator == to compare a string and a key types returns empty. Using the operator ~= which attempts to coerce appears to return the expected result:
%dw 2.0
output application/json
var attributeIdMapping =
{
"attributes": [
{
"name": "accountType",
"id": "87"
},
{
"name": "accountClass",
"id": "89"
},
{
"name": "accountName",
"id": "85"
},
{
"name": "displayName",
"id": "18"
},
{
"name": "accountCategory",
"id": "88"
},
{
"name": "accountNumber",
"id": "84"
},
{
"name": "description",
"id": "86"
},
{
"name": "accountGroup",
"id": "90"
}
]
}
var requestBody = {
"displayName": "TestMulesoft2",
"description": "Test"
}
--- {
"objectTypeId": 3,
"attributes": requestBody mapObject (value, key) ->
{
"objectTypeAttributeId": (attributeIdMapping.attributes filter ($.name ~= key))[0].id,
"objectAttributeValues": [{
"value": value,
"key": key
}]
} }
Output:
{
"objectTypeId": 3,
"attributes": {
"objectTypeAttributeId": "18",
"objectAttributeValues": [
{
"value": "TestMulesoft2",
"key": "displayName"
}
],
"objectTypeAttributeId": "86",
"objectAttributeValues": [
{
"value": "Test",
"key": "description"
}
]
}
}

Error when saving composites id inside a for loop

I am trying to persist some objects that have a composite id. If I am only sending an array with one element it works fine, but it the array has more than one it throws an exception when saving the first one. public boolean
addParamsToChart(List<ChartParams> chartParams, Long chartId) {
List<ChartParams> chartParamsList = new ArrayList<>();
for(ChartParams chartParam: chartParams) {
ChartParamsId id = new ChartParamsId();
// id.setChartId(chartId);
id.setChartId(chartParam.getChart().getId());
id.setParamId(chartParam.getParam().getId());
id.setContextSourceId(chartParam.getContextSource().getId());
chartParam.setChartParamsId(id);
if(chartParamsRepository.save(chartParams) !=null) {
chartParamsList.add(chartParam);
}
}
if(chartParamsList.size()!=chartParams.size()) {
// something went wrong, delete previous inserted
deleteChartParams(chartParamsList);
chartRepository.delete(chartId);
return false;
}
return true;
}
[{
"chart": {
"id": 49,
"cv": {
"id": 1,
"name": "Money",
"category": {
"id": 1,
"name": "Euros"
},
"definition": "\"European curreny.\" [EU:euro]",
"enabled": true,
"cvid": "CC:1010"
},
"accountType": {
"id": 1,
"name": "saving"
},
"name": "Euro saving charts"
},
"param": {
"id": 8,
"name": "Totals",
"isFor": "Currency"
},
"contextSource": {
"id": 3,
"name": "euro",
"internal": "eu",
"abbreviatedName": "eu"
} }]
But for this having two objects inside instead of one is not working, throwing an exception at the first save.
[{
"chart": {
"id": 52,
"cv": {
"id": 55,
"name": "Stocks",
"category": {
"id": 1,
"name": "Stocks"
},
"definition": "\"General stocks.\" [GS:ST]",
"enabled": true,
"cvid": "ST:0111"
},
"accountType": {
"id": 1,
"name": "saving"
},
"name": "Stock saving chart"
},
"param": {
"id": 8,
"name": "Totals",
"isFor": "Currency"
},
"contextSource": {
"id": 6,
"name": "stock",
"internal": "st",
"abbreviatedName": "st"
} }, {
"chart": {
"id": 52,
"cv": {
"id": 55,
"name": "Stocks",
"category": {
"id": 1,
"name": "Stocks"
},
"definition": "\"General stocks.\" [GS:ST]",
"enabled": true,
"cvid": "ST:0111"
},
"accountType": {
"id": 1,
"name": "saving"
},
"name": "Stock saving chart"
},
"param": {
"id": 8,
"name": "Totals",
"isFor": "Currency"
},
"contextSource": {
"id": 7,
"name": "Sold stock",
"internal": "st_sold",
"abbreviatedSequence": "st_sold"
} }]
The exception I got is:
org.hibernate.id.IdentifierGenerationException: null id generated for:class eu.stocks.chart.chartParams.ChartParams

Resources