问题
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_camera
has 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
?
回答1:
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.
回答2:
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)
来源:https://stackoverflow.com/questions/57680929/how-to-query-a-third-relation-in-ecto-associations