Laravel MongoDB group by - php

I'm currently using jenseggers-mongodb eloquent in laravel 5 with mongodb 3.0.3.
I'm trying to join two different tables as follows:
User Model
public function userpayment() {
return $this->hasMany('App\Models\Userpayment', 'user_id', '_id');
}
Userpayment model
public function user() {
return $this->belongsTo('App\Models\User','user_id');
}
I'm using repository pattern
public function __construct() {
$this->model = new User;
}
return $this->model->with(array('userpayment'=>function($query){
$query
->groupBy('dealCodeNumber')
->get();
}))
->where('_id',$sid)
->get();
groupBy dealCodeNumber returns NULL.
array:1 [▼
0 => array:15 [▼
"_id" => "55813f4cbc59a3f1372e9e6f"
"full_name" => "Varathan"
"username" => "shopsyadmin"
"web_url" => ""
"userpayment" => []
]
without groupby returns all.
array:1 [▼
0 => array:15 [▼
"_id" => "55813f4cbc59a3f1372e9e6f"
"full_name" => "Varathan"
"username" => "shopsyadmin"
"userpayment" => array:2 [▼
0 => array:57 [▼
"_id" => "55816ce7cc7d4bac0d000029"
"dealCodeNumber" => "1398410837"
"inserttime" => "1398411401"
"status" => "Pending"
]
1 => array:57 [▶]
]
Querylog with groupby
[query] => shopsy_user_payment.aggregate([{"$match":{"user_id":{"$in":["55813f4cbc59a3f1372e9e6f"]}}},{"$group":{"_id":{"dealCodeNumber":"$dealCodeNumber"}
Why groupby returns null?

To group an column it must be selected before grouping. Changing code to below works:
return $this->model->with(array('userpayment'=>function($query){
$query
->select('product_id','user_id','dealCodeNumber')
->groupBy('dealCodeNumber')
->get();
}))
->where('_id',$sid)
->get();

Related

Merge arrays on Laravel

I'm new in Laravel and I'm trying to merge or join to arrays in one array, which have a one-to-many relationship.
These are the models:
class GroupMenu extends Model
{
public function optionmenu()
{
return $this->hasMany(OptionMenu::class, 'groupmenu_id');
}
}
class OptionMenu extends Model
{
public function groupmenu()
{
return $this->belongsTo(GroupMenu::class, 'groupmenu_id');
}
}
Also I have this function which returns the following arrangement.
public function getOptionMenus()
{
$optionmenu = OptionMenu::whereHas('tipousuario', function ($query) {
$query->where('tipousuario_id', session()->get('tipousuario_id'))->orderBy('orden');
})->get()->toArray();
return $optionmenu;
}
The output is like that:
array:17 [▼
0 => array:2 [▼
"id" => 1
"groupmenu_id" => 1
]
1 => array:2 [▼
"id" => 2
"groupmenu_id" => 1
]
2 => array:2 [▼
"id" => 3
"groupmenu_id" => 1
]
3 => array:2 [▼
"id" => 4
"groupmenu_id" => 2
]
4 => array:2 [▼
"id" => 5
"groupmenu_id" => 2
]
My problem is that I want to have an array where for each groupmenu has within it the array of the optionmenu, something like that:
0 => array:2 [▼
"id" => 1
"optionmenu" => array:3[array of all the optionsmenu that belongs to the groupmenu]
]
1 => array:2 [▼
"id" => 2
"optionmenu" => array:1[array of all the optionsmenu that belongs to the groupmenu]
]
If you want to get all GroupMenu records with related OptionMenu records without any constraint
$data = GroupMenu::with('optionmenu')->get();
However if you want to constrain the related OptionMenu records for each GroupMenu parent record based on the id of tipousuario - which you get from session as shown in your question then you can try something like
$data = GroupMenu::with([
'optionmenu' => fn($query) =>
$query->whereHas('tipousuario', fn($q) =>
$q->where('tipousuario_id', session()->get('tipousuario_id'))->orderBy('orden')
)
])->get();

Laravel working with nested collection delete nested branch

unable to delete all nested branches where "product" => null
Have a query
$cartWhere['user_id'] = $user_id;
$cartWhere['site_id'] =$currentSite->id;
$item = Cart::select('product_id','quantity')->with(['product' => function($product) use ($search){
$product->join('product_translations', 'products.id', '=', 'product_translations.product_id');
$product->where( 'product_translations.name', 'LIKE','%'.$search.'%');
},'product.manufacturer:id,name'])
->where($cartWhere)->get();
then I receive collection that has all filtered carts but some of these carts have a relation with product => null
1 => App\Models\Cart {#736 ▼
...
#original: array:2 [▼
"product_id" => 1
"quantity" => 2
]
...
#relations: array:1 [▼
"product" => App\Models\Product {#785 ▶}
]
}
2 => App\Models\Cart {#736 ▼
...
#original: array:2 [▼
"product_id" => 2
"quantity" => 2
]
...
#relations: array:1 [▼
"product" => null
]
}
sorry for my English
You can filter them from the results using the collections filter() method
$item = Cart::select('product_id','quantity')
->with(['product' => function($product) use ($search) {
$product->join('product_translations', 'products.id', '=', 'product_translations.product_id');
$product->where( 'product_translations.name', 'LIKE','%'.$search.'%');
}, 'product.manufacturer:id,name'])
->where($cartWhere)
->get()
->filter(function ($cart) {
return $cart->product !== null;
});
Along with with you should use whereHas. So the result will not include any relation with null value. So this way you can also avoid the extra filter method used.

How to return the list of objects and their count

I want to replace the COUNT(ID) with the list of objects
i want to return an array containing the list of objects instead of returning
their count
my code:
$data['myresponse'] = DB::table("products")
->where('id_advisor',$advisor->id)->where('deleted_at', NULL)
->where('created_at',">=", $start)->where('created_at',"<=", $end)
->select(DB::raw("DATE(created_at) as date,COUNT(id) objects"))
->groupBy(DB::raw('Date(created_at)'))
->get();
the response:
{
"data": {
"myresponse": [
{
"date": "2020-07-03",
"objects": 2
},
{
"date": "2020-07-05",
"objects": 4
},
{
"date": "2020-07-08",
"objects": 8
},
{
"date": "2020-07-09",
"objects": 17
}
]
}
}
what i need is to return something like this:
enter image description here
I would approach it from the other side. Select your objects and put them into the date buckets.
Laravel can help you out of the box grouping it per attribute. You'll only need to map it to the desired struct.
$products = DB::table("products")
->where('id_advisor',$advisor->id)->where('deleted_at', NULL)
->where('created_at',">=", $start)->where('created_at',"<=", $end)
->get()
->groupBy('created_at');
**Original bits of code example **
Below is some (pseudo) code as an example over the reverse approach.
$products = DB::table("products")
->where('id_advisor',$advisor->id)->where('deleted_at', NULL)
->where('created_at',">=", $start)->where('created_at',"<=", $end)
->get();
$buckets = $products->map(
function($product) {
return $product->created_at;
}
)->unique();
$result = $buckets->map(function ($bucket) use ($products) {
return [
'date' => $bucket,
'products' => $products->filter(
function($product) use ($bucket) {
return $product->created_at === $bucket;
}
)
];
});
dd($results);
Dump result:
Illuminate\Support\Collection {#1050
#items: array:3 [
0 => array:2 [
"date" => "2020-07-03"
"products" => Illuminate\Support\Collection {#1048
#items: array:1 [
0 => array:2 [
"date" => "2020-07-03"
"id" => 1
]
]
}
]
1 => array:2 [
"date" => "2020-07-04"
"products" => Illuminate\Support\Collection {#1047
#items: array:2 [
1 => array:2 [
"date" => "2020-07-04"
"id" => 2
]
2 => array:2 [
"date" => "2020-07-04"
"id" => 3
]
]
}
]
3 => array:2 [
"date" => "2020-07-05"
"products" => Illuminate\Support\Collection {#1045
#items: array:1 [
3 => array:2 [
"date" => "2020-07-05"
"id" => 4
]
]
}
]
]
}
try this
$data['myresponse'] = DB::table("products")
->where('id_advisor',$advisor->id)->where('deleted_at', NULL)
->where('created_at',">=", $start)->where('created_at',"<=", $end)
->select(DB::raw("DATE(created_at) as date, DB::raw('count(*) as objects'))
->groupBy(DB::raw('DATE(created_at)')) // or ->groupBy('date')
->get();

Group Attributes into Sets from Variant Attribute Relation

I'm trying to create a collection of Attributes using model bindings and group the attributes into sets before outputting as a resource. I have my relationships set as follows:
Variant Model App\Variant
public function attributes()
{
return $this->belongsToMany(Attribute::class, 'variant_attributes')
->withPivot('value');
}
Attributes Model App\Attribute
public function variants()
{
return $this->belongsToMany(Variant::class, 'variant_attributes');
}
public function set()
{
return $this->belongsTo(AttributeSet::class, 'attribute_set_id');
}
Attribute Sets Model App\AttributeSet
public function attributes()
{
return $this->hasMany(Attribute::class);
}
Ideal Output
Illuminate\Database\Eloquent\Collection {#718 ▼
#items: array:2 [▼
"essentials" => array:2 [▼
"name" => "Essentials"
"attributes" => array:2 [▼
"repellendus" => array:2 [▼
"name" => "repellendus"
"value" => "1"
]
"incidunt" => array:2 [▶]
]
]
"interior" => array:2 [▶]
]
}
Essentials and Interior are the Attribute Sets and their associated attributes are the children with the key of attributes. The pivot value comes from the variant_attributes table. I am also binding the Product and Variant to a controller...
Now, this is what I have done, however it doesn't feel right whatsoever calling $variant = $attribute->variants->first(); on a belongsToMany in this instance. I also feel this is overcomplicated.
$attributeSets = AttributeSet::with(['attributes.variants' => fn($query) => $query->withPivot('value')->where('id', $variant->id)])
->whereHas('attributes.variants', fn($query) => $query->where('id', $variant->id))
->get();
$attributeSets = $attributeSets->mapWithKeys(function ($attributeSet) {
$attributes = $attributeSet['attributes']->filter(function ($attribute) {
return $attribute->variants->count();
})->mapWithKeys(function ($attribute) {
$variant = $attribute->variants->first();
return [
$attribute['identifier'] => [
'name' => $attribute['name'],
'value' => $variant['pivot']['value']
]
];
})->toArray();
return [
$attributeSet['identifier'] => [
'name' => $attributeSet['name'],
'attributes' => $attributes
]
];
});
Thanks in advance!

Laravel join with sub query

I have two models User and Address, one user can have many addresses but I want to fetch only which is primary(where primary=true)
this is what I have tried, and I am getting multiple users in the list
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
I tried this too but I am not getting any data
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->where('addresses.primary', true)
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
thank you
Collection {#375 ▼
#items: array:8 [▼
0 => User {#376 ▶}
1 => User {#377 ▼
#attributes: array:9 [▼
"name" => "Colin Sushanth"
"phone_number" => "9987217545"
"address" => "2nd Cross 3rd street, y this is my address"
"landmark" => "Near the address"
"city" => "Mangalore"
"state" => "Karnataka"
"pincode" => 575002
"status" => "valid"
"primary" => "true"
]
}
2 => User {#378 ▶}
]
}
You should try this:
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->where('addresses.primary','=',1)
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
Or:
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->where('addresses.primary','=',true)
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
Updated answer
Blade file:
#if(isset($users))
#foreach($users as $user)
#if($user->primary === 'true')
//Your code
#endif
#endforeach
#endif
I would do it using eloquent models
So you would u do
User::whereHas('primary')->pluck('name','phone_number','address','landmark','city','state','pincode','users.status')
and your model will look like this
public function addresses()
{
return $this->belongsTo('App\Models\Address');
}
public function primary()
{
return $this->addresses->primary == true;
}

Categories