Laravel: relationship between siblings - laravel

I have 4 tables flats, residents, floors & resident_floors. The relations between them is as follows:
flats:
id | name
-----------------------------
1 | Flat -1
2 | Flat -2
...
flat_residents:
id | flats_id | name
-----------------------------
1 | 1 | Resident - 1
2 | 2 | Resident - 2
3 | 3 | Resident - 3
...
flat_floors:
id | flats_id
-----------------------------
1 | 101
2 | 102
3 | 201
4 | 202
...
flat_resident_floors:
id | residents_id | floors_id
-----------------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
4 | 3 | 4
I am trying to create the relationship between them to display the data as follows:
Flat / Floor(s) | Resident
1 / 101, 102 | Resident - 1
2 / 201 | Resident - 2
3 / 202 | Resident - 3
Resident.php
public function floors()
{
return $this->hasManyThrough(Floor::class, ResidentFloor::class, 'floors_id', 'id');
}
Here is the query which is being generated:
SELECT * FROM floors
INNER JOIN flat_resident_floors ON flat_resident_floors.id = floors.id
WHERE flat_resident_floors.floors_id = ?
Where as it should be:
SELECT * FROM floors
INNER JOIN flat_resident_floors ON flat_resident_floors.floors_id = floors.id
WHERE flat_resident_floors.residents_id = ?
I don't understand what or where am I doing wrong..?

Don't think about the underlying SQL so much, instead use the Eloquent relationships to your advantage. In this case, it seems that Flat should hasMany(Floor::class) and Floor should hasMany(Resident::class). Your Flat then hasManyThrough relationship with Resident which writes itself (without needing a pivot table as you are trying to do).
class Floor
{
public function residents()
{
return $this->hasMany(Resident::class);
}
public function flat()
{
return $this->belongsTo(Flat::class);
}
}
class Resident
{
public function floor()
{
return $this->belongsTo(Floor::class);
}
}
class Flat
{
public function floors()
{
return $this->hasMany(Floor::class);
}
public function residents()
{
return $this->hasManyThrough(Resident::class, Floor::class);
}
}

Related

Eloquent how to get Sum of a column separated by 2 has many relationships

I am trying to get the sum of a column of another table that is 2 hasMany relationships away. Ideally I would like to use eloquent and not use raw queries or joins.
Table structure
factions table
id
example rows
1
2
3
islands table
id | faction_id
example rows
1 | 1
2 | 2
3 | 3
4 | 1
5 | 2
6 | 3
shrines table
id | island_id | points (integer)
example rows
1 | 1 | 200
2 | 2 | 100
3 | 3 | 50
4 | 4 | 75
5 | 5 | 200
6 | 6 | 100
7 | 1 | 25
8 | 2 | 40
9 | 3 | 50
Relationships:
Faction hasMany Island
Island hasMany shrines
I would like to be able to get all Factions and get the sum of the points that effectively belong to each faction where the result is something like
$factions = [
['id' => 1, 'points' => 300],
['id' => 2, 'points' => 340],
['id' => 3, 'points' => 200],
...
]
so points in the sum of the shrines.points that belongs to the islands that belongs to the faction.
Any help is appreciated and I've found a few posts that talk about similar problems but the problem isn't exactly the same and the solution isn't exactly what I am looking for.
If you add a hasManyThrough relationship on your Faction model, you should be able to use an accessor to do it:
Faction.php
protected $appends = ['points'];
public function shrines(){
return $this->hasManyThrough(Shrine::class, Island::class);
}
public function getPointsAttribute(){
return $this->shrines()->sum('points');
}

add AlternateKey to model in asp.net

i have one table like this
id
version
secondId
1
1
1000
1
2
1000
1
3
1000
2
1
1001
2
2
1001
2
3
1001
verion and id are composite key . i want to add auto increment secondId . for all id , secondId is same but version is diffrent. i dont konw how to handle this in code first EF .
i write blow code in dbcontext file
modelBuilder.Entity<user>().HasKey(e => new { e.Id, e.Version });
modelBuilder.Entity<user>().HasAlternateKey(q => new { q.Version, q.SecondId });
modelBuilder.Entity<user>().Property(q => q.SecondId).UseIdentityAlwaysColumn();
modelBuilder.Entity<user>().Property(q => q.SecondId).HasIdentityOptions(1000);

Laravel model query with sum and grouping

I have a table like this:
|item_name |uom |qty |order_number
|bike |pc |1 |101
|ball |pc |2 |102
|bike |pc |5 |103
|car |pc |3 |106
|bike |pc |4 |108
|ball |pc |1 |109
|bike |pc |6 |115
|car |pc |1 |111
And I want to see in a view this data:
bike - 16 pcs overall:
101 - 1
103 - 5
108 - 4
115 - 6
ball - 3 pcs overall:
102 - 2
109 - 1
etc...
I tried wuth this query, but I think it is not correct, because it gives me only name and sum of qty:
$saps = Item::where('year', 2019)->groupBy('item_name')->selectRaw('item_name, sum(qty) as sum')->get('item_name','sum');
Item::where('year', 2019)
->select('name','order_number',\DB::raw("SUM(qty) as qty"))
->groupBy('name')
->havingRaw('COUNT(*) > 1')
->get();
Try this query.
Outupt
Try this query.
$saps = Item::where('year', 2019)->selectRaw('order_number, qty')
->groupBy('item_name')
->get();
Or
$saps = Item::where('year', 2019)->selectRaw('order_number, qty,item_name')
->get();
$saps_new = $saps->groupBy('item_name')->map(function ($row) {
return $row->sum('qty');
});
You can get the initial groups with this:
$saps = Item::where('year', 2019)->selectRaw("SUM(qty) as total, item_name, id")
->groupBy('item_name')
->get();
You can then lazy or eager load the listing for each item.
If you go with lazy loading you can map on results and then lazy load the listing based on each item
$saps->map(function($item){
$items = Item::where('year', 2019)->where('item_name', $item->item_name)
->get();
}
or eager load like this:
Item::where('year', 2019)->whereIn('item_name', $saps)
->get();

Multiple Scheduled in the same method

I'm working with #Scheduled annotations. I need to run the method in different moments, exactly each 2 and 5 seconds.
How can I do it?
In this moment my code is the next:
#Scheduled(cron = "${cron.startdate}")
public void check() {
LOGGER.info("1 - Check DB");
}
and the application.yml:
cron:
startdate: 0/2 * * * * *
My configuration will be executed each 2 seconds, but I need it to be executed each 5 seconds too.
The output should be:
[11:20:00] | 1 - Check DB
[11:20:02] | 1 - Check DB
[11:20:04] | 1 - Check DB
[11:20:05] | 1 - Check DB
[11:20:06] | 1 - Check DB
[11:20:08] | 1 - Check DB
[11:20:10] | 1 - Check DB
[11:20:12] | 1 - Check DB
.
.
.
Thanks guys.
I think #Scheduled(cron = "0/2,0/5 * * * * *") should work.

ElasticSearch advanced scoring with Nested Date Ranges and today > tomorrow > yesterday

Here's my data model in ES:
{
id: 1,
dateRanges: [
{ from: 2014-01-01, to: 2014-01-05 },
{ from: 2014-01-08, to: 2014-01-10 },
...
]
}
Now I'd like to score my documents depending on the current date. PSEUDOCODE:
SCORE =
if( today IS IN any dateRange ) {
return MAX_VALUE;
} else if( today < any dateRange.from ) {
dateRange.from = lowest dateRange.from, which is > today;
return 1 / ( dateRange.from - today );
} else {
dateRange.to = highest dateRange.to, which is < today;
return dateRange.to - today;
}
Example:
id | dateRange1 | dateRange2 | ...
-------------------------------------------------------------------
1 | 2014-01-01 to 2014-01-10 | 2014-01-12 to 2014-01-13 |
2 | 2014-01-03 to 2014-01-03 | |
3 | 2014-01-01 to 2014-01-02 | 2014-01-10 to 2014-01-15 |
today = 2014-01-11
The result should be in this order: 3 1 2
Reason:
3 gets the highest scoring because today is within at least one of the date ranges
1 gets the second highest scoring, because it has at least one date range where dateRange.from > today
2 gets the lowest scoring, because all of its date ranges have dateRange.to < today
Does anyone know how to do it?
Thanks for your help :)

Resources