Let’s suppose that I have
{
users {
...
review {
...
}
}
}
Users might have or not a Review, Is there a way to hide a user in the results that does not have a review? I’m fetching the review using Dataloader. I don’t want a return like
{
users: [
{..., review: {...}},
{..., review: {...}},
{..., review: null},
{..., review: null}
...
]
}
Hey @devmarco it sounds like you want to filter users by whether they have a review . If so, you should look at introducing an argument to the reviews field:
{
users(withReviews: true) {
...
}
}
If you never want to return users without reviews, then update your users
resolver to always do the requisite join to filter out users without reviews.
1 Like
@benwilson512 I end up with this approach but the review is fetched using dataloader, so it receives the user object. and when I filter the users with something like
args
|> filter_query
|> Repo.all()
**Only users that have a review.** (Work)
{:with_review, true}, query ->
from(q in query,
join: r in assoc(q, :review),
where: not is_nil(r)
)
**Only users that do not have a review.** (Do not Work)
{:with_reviews, false}, query ->
from(q in query,
inner_join: r in Review,
on: q.id != r.user_id,
select: {q, r}
)
Can you show some more code? Is that inside dataloader? If so, are you loading the users with dataloader?
Users are not loaded using dataloader just the review inside it.
def list_users(args \\ %{}) do
args
|> filter_query
|> Repo.all()
end
def get_review(_, %{id: id}, %{context: %{loader: loader}}) do
loader
|> Dataloader.load(Reviews, Reviews.Review, id)
|> on_load(fn loader ->
review = Dataloader.get(loader, Reviews, Reviews.Review, id)
{:ok, review}
end)
end
query {
users(withReviews: true/false) {
review {
...
}
}
}
The filter_query function is the place that I’m trying to apply the query filters (Following the example in the book). So when I call list_users
, it will goes through my filter function
defp filter_query(args) do
Enum.reduce(args, User, fn
{:filter, filter}, query ->
query |> filter_with(filter)
end)
end
defp filter_with(query, filter) do
Enum.reduce(filter, query, fn
{:with_review, true}, query ->
from(q in query,
join: r in assoc(q, :review),
where: not is_nil(r)
)
{:with_review, false}, query ->
from(q in query,
join: r in assoc(q, :review),
where: is_nil(r)
)
_, query ->
query
end)
end
I want to find a way to return only users that do not have a review.
You need to left_join
when with_review
is false. In the :with_review, true
clause you don’t need the here
, a regular inner join will only include rows where the review is there anyway.
@benwilson512 you were right, thank you to help me on that.
from(
q in query,
left_join: r in assoc(q, :review),
where: is_nil(r)
)
HI @benwilson512 I face this problem with dataloader. How can I do?