"Second Newest" in has_many

I'm trying to set up a relationship or calculation that can let me express the "second newest" item in a has_many relationship. Grabbing the most recent is easy peasy:
elixir
has_one :most_recent_log, MyLog do
public? true
from_many? true
sort inserted_at: :desc
end
elixir
has_one :most_recent_log, MyLog do
public? true
from_many? true
sort inserted_at: :desc
end
Ideally I'd be able to do something like:
elixir
has_one :second_most_recent_log, MyLog do
public? true
from_many? true
sort inserted_at: :desc
offset 1
end
elixir
has_one :second_most_recent_log, MyLog do
public? true
from_many? true
sort inserted_at: :desc
offset 1
end
But offset isn't available to a has_one relationship. What's the proper way to do this?My use case is to just display the difference between the most_recent_log.score and second_most_recent_log.score. I've tried a handful of different approaches at this point and none of them have panned out. Can't help but think there's a simple way I'm just not seeing.
5 Replies
Rise
Rise2mo ago
This is also something I am trying to figure out right now but what could be the solution is to just use a mix of loading and sorting like shown in the docs
posts = MyApp.Blog.list_posts!(
query: [
filter: [
author: [verified: true],
comments_count: [greater_than: 5]
]
]
)
posts = MyApp.Blog.list_posts!(
query: [
filter: [
author: [verified: true],
comments_count: [greater_than: 5]
]
]
)
https://hexdocs.pm/ash/read-actions.html and put the logic into a calculation Also probably has_many is more suitable in this case even if it’s only two?
⿻ eileen
⿻ eileenOP2mo ago
Yeah I'm putting the logic into a calculation now, but I was hoping there was a way to do it purely in expressions so I could push it to the data layer Probably not an important optimization though, tbh I have tried many variations involving has_many. None of them allow me to get the difference of score1 - score2, so far
Rise
Rise2mo ago
Also for the latest you can use aggregate do First : name, : field End Yeah having some kind of calculation between different object is difficult without custom calculations from what I have seen, but I am new to ash The question is how would the SQL statement look like. If it’s not trivial then ash is probably also not that easy. Just my feeling
⿻ eileen
⿻ eileenOP2mo ago
That makes sense! Seems simple in concept. Calculate the difference between result1.score and result2.score, when ordering by [inserted_at: desc]. But in practice, not so much
ZachDaniel
ZachDaniel2mo ago
make a first relationship and filter where the id of the second does not equal the id of the first and sort by the thing you want to sort by
has_one :second_biggest_thing, Thing do
filter expr(id != parent(first_biggest_thing.id))
sort [number: :desc]
end
has_one :second_biggest_thing, Thing do
filter expr(id != parent(first_biggest_thing.id))
sort [number: :desc]
end

Did you find this page helpful?