bglusman

bglusman

So I have a gnarly query in my open source Phoenix app I was trying to make dramatically more efficient.. in its current form it brings in a lot of unnecessary data over the wire, so I managed to get a raw SQL form that only gets the data I need, and tried translating it into Ecto, and got stuck with some errors related to group_by vs select I think… the purpose is to get the data we need, which is stocks that have a “path” to any of the credit_types in the database, grouped by which credit type(s) they have a path to (most only have one path, but some have 2, and in that case we want the stock duplicated and to appear in a column for both credit types)… in it’s current form (in Ecto, before attempted refactor) it works but it pulls every food in the database also, because they all relate to one or more credit types, but we only care about “stocked” foods. Current form goes from credit_type “toward” stocks, the refactor works by going from stocks “toward” credit type, and grouping stocks by credit type…

Here is the raw SQL version:

    select stock.id, food.long_desc, food.manufacturer_name, food_group.foodgroup_desc,
      credit_type.name
      from facilities facility
      inner join stocks stock on stock.facility_id = facility.id
      inner join foods food on food.id = stock.food_id
      inner join credit_type_memberships ctm on ctm.food_group_id = food.food_group_id
      inner join credit_types credit_type on credit_type.id = ctm.credit_type_id
    where facility.id = 1
    group by stock.id, food.long_desc, food.manufacturer_name, food_group.foodgroup_desc,
      credit_type.name

And rather than paste the non-working ecto-translation of it here, I’ll link in context to my best/closest attempt I think I got to, in the branch I was playing with it on… the play function here was accidentally committed ages ago while trying to solve the same problem, before I had a working SQL version of it, just to make it easy to test the query in iex… the stock_by_type function above it is the actual query from the app as currently used. You can probably answer any question from the code in the link there, (and original form of that query before the WIP/play commit above is actually changed here for reference) but also happy to provide context if anything is unclear/harder to find an answer to than you’d like, but you’re otherwise interested in helping with the refactor… Thanks all!

Showing Posts 29 to 20

bglusman

bglusman OP

I put this to the side after we came full circle back to probably using group_by, but I opened a github issue for it, and a contributor appears to have solved the problem differently than I was trying to, but it seems to be OK, and certainly better than it was. PR here:
https://github.com/openpantry/open_pantry/pull/152

kip

kip

ex_cldr Core Team

Agree @cmkarlsson, not complex at all - bad characterisation on my part.

bglusman

bglusman OP

Hah, full circle :slight_smile: and yes, they do, not a huge number, but enough…

OvermindDL1

OvermindDL1

This might be a good use for group_by then. It is likely happening because multiple stocks join to the same/multiple credits.

bglusman

bglusman OP

Oh, cool, I was trying to select on that before but was getting an error about the binding not matching, but now I have that working, though now it seems to give me duplicate credit types somehow instead of duplicate stocks within a single credit type… this is the current query, which is maybe promising but it seems slower than it was before:

  def play() do # way more data than needed, but one query! :-/
    id = 1
    today = DateTime.utc_now
            |> DateTime.to_date
            |> Ecto.Date.cast!

    from(stocks in Stock,
      join:  food_credit_types in assoc(stocks, :credit_types),
      select: food_credit_types,
      where: ^id == stocks.facility_id,
      where: stocks.arrival < ^today,
      where: stocks.expiration > ^today,
      order_by: food_credit_types.id,
      preload: [stocks: [food: :food_group]])
    |> Repo.all
  end

Not totally sure at a glance if it’s pulling all foods form DB now or not… my guess is that it is, but, harder to tell than it was in the shape it was in before

As far as duplicates thing, if I pipe above query to map name:
|> Enum.map(&(&1.name))
then with only 3 credit types I get 6 names,
["Veggienoms", "Carbnoms", "Proteinoms", "Proteinoms", "Proteinoms", "Proteinoms"] which must be, like, the 3 or 4 foods in food groups that are both proteins and veggies or something I think, some of them repeating? Hard to reason about at a glance, but sort of seems like progress… merging those together into one struct per name/id wouldn’t be so bad though if it is avoiding pulling all the food, but like I said, at a glance I think the query is now slower by like 100% or so than the old version

OvermindDL1

OvermindDL1

At the very least to start with if you want to return a list of CreditTypes then you should add a select: statement doing so from your food_credit_types join. :slight_smile:

bglusman

bglusman OP

Also this isn’t urgent @OvermindDL1 so please, appreciate all your help but feel free to check back in in a day or 3 if busy now but interested enough to help later! I appreciate the input and thoughts!

bglusman

bglusman OP

There won’t be a TON of overlap, but where there is we want it… mostly its about things like beans/legumes which are both a veggie and a protein, in our specific use case, and a few other foods that cross over some boundaries so we allow both credit types to be used for them… I got the Ecto query working as I expected, and like I said, now it’s a list of stocks :slight_smile:

Here’s a workign query I’d like to turn “inside out”:

  def play() do
    id = 1
    today = DateTime.utc_now
            |> DateTime.to_date
            |> Ecto.Date.cast!

    from(stocks in Stock,
      join:  food_credit_types in assoc(stocks, :credit_types),
      where: ^id == stocks.facility_id,
      where: stocks.arrival < ^today,
      where: stocks.expiration > ^today,
      order_by: food_credit_types.id,
      preload: [food: [food_group: :credit_types]])
    |> Repo.all
  end
OvermindDL1

OvermindDL1

Once we talk in a thread then by default we get notified on updates on it. :slight_smile:

I’m still a bit short on time, but quick question, since you want the CreditType structs, do you expect a lot of the same stocks and foods structs too, or will they all be pretty much distinct? Which answer determines which is the best way to do it. :slight_smile:

bglusman

bglusman OP

that wasn’t done as a reply to any of you so you may not see it.. @OvermindDL1 / @cmkarlsson / @kip

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews