0
votes
Snapmail
|> preload(:user)
|> preload(:snapmail_cameras)
|> preload([snapmail_cameras: :camera])
|> preload([snapmail_cameras: [camera: :vendor_model]])
|> preload([snapmail_cameras: [camera: [vendor_model: :vendor]]])
|> Repo.all

I have above query in Ecto. in this. Each snapmail has a snapmail_camera and snapmail_camerahas a camera_id which is camera's id (from camera table.)

and Cameras table has a field status.

I am trying to get only those snapmails where its snapmail_cameras's camera's status is not equal to project_finished

this is the relation of snapmail and snapmail_camera

belongs_to :user, User, foreign_key: :user_id
has_many :snapmail_cameras, SnapmailCamera

any help would be so thankful. How I can get those snapmails?

2

2 Answers

1
votes

You're preloading a ton, which will get you lots of data you could filter our in code, but the database can return much less data if you use join/5:

Assuming I've interpreted your scheme correctly, here's what I'd do.

import Ecto.Query

query =
  from s in MyApp.Snapmail,
  join: sc in assoc(s, :snapmail_cameras),
  join: c in assoc(sc, :camera),
  where: c.status != ^"status_finished"

MyApp.Repo.all(query)

This will only return Snapmails without all those preloads, but you can always add a `preload/3' at the end of your query to bring that data in.

-1
votes

Executing

Snapmail |> Repo.preload([snapmail_cameras: :camera]) |> Repo.all()

Returns a list containing all Snapmails: [%Snapmail{},...]

Each Snapmail struct would look like this

%Snapmail{
 snapmail_cameras: [
  %SnapmailCamera{
     camera: %Camera{
               status: "status" 
             }
   }, ... 
 ]
}

At this point, you could use the filter function

Enum.filter(snapmails, 
fn snapmail-> snapmail.snapmail_cameras 
|> Enum.all?(fn snapmail_camera -> snapmail_camera.status != "project_finished" end) 
end)