Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to fetch entity and all related ones #486

Closed
Sytten opened this issue Jan 23, 2022 · 5 comments · Fixed by #813
Closed

Allow to fetch entity and all related ones #486

Sytten opened this issue Jan 23, 2022 · 5 comments · Fixed by #813
Assignees
Milestone

Comments

@Sytten
Copy link
Contributor

Sytten commented Jan 23, 2022

Consider the following example (where a release has multiple release_links):

let result = releases::Entity::find()
                .find_with_related(release_links::Entity)
                .order_by_desc(releases::Column::ReleasedAt)
                .all(conn)
                .await?;

This returns a Vec<(Model, Vec<Model>)>. Changing .all to .one yields a Option<(Model, Option<Model>)>.
For a One-to-Many relation this is really weird, what is expected is Option<(Model, Vec<Model>)>.

@billy1624
Copy link
Member

Hey @Sytten, basically, calling one returns the first pair of related model i.e. Option<(Model, Option<Model>)>. And, calling all returns all of the pairs, Vec<(Model, Vec<Model>)>.

For a one-to-many relation you can expect the behaviour stated above happened.
But for a one-to-one relation you can expect both one and all will return zero or one pair of related model.

@Sytten
Copy link
Contributor Author

Sytten commented Jan 24, 2022

I guess then there should be a first which would return a Option<(Model, Vec<Model>)>? Basically the same query as all but with a LIMIT 1 on the parent for performance reasons.

@isgj
Copy link

isgj commented Feb 14, 2022

That will complicate the query builder as there is no easy way to limit on one of the join tables. It can be achieved with a subquery like:

select releases.id, other_col
from releases
join release_links on ....
where releases.id in (
    select releases.id 
    from releases 
    where ... 
    limit 1
)

and if the conditions involve both the tables the join should happen also in the subquery.

I guess you can do:

let result = releases::Entity::find()
                .filter(
                              Condition::any().add(
                                  releases::Column::Id.in_subquery(
                                      Query::select()
                                          .column(releases::Column::Id)
                                          .from(releases::Entity) // if required you can add other conditions here in the subquery
                                          .limit(1)
                                          .to_owned()
                                  )
                              )
                  )
                .find_with_related(release_links::Entity)
                .order_by_desc(releases::Column::ReleasedAt)
                .all(conn)
                .await?;

The result will be of type Vec<(Model, Vec<Model>)> and the len at most 1

@tyt2y3
Copy link
Member

tyt2y3 commented Mar 31, 2022

This is a very interesting sugguestion. First of all, if you only need one and all it's related models, then find_related on the model itself is the recommended way.

Anyway, thanks @isgj for pointing out this is a non-trivial problem. We have to know the "one" in order to limit the query, so the solution is either 1) two queries or 2) sub query

Perhaps removing one from SelectTwo is the most reasonable resolution for now?

@tyt2y3 tyt2y3 added this to the 0.9.0 milestone May 15, 2022
@billy1624 billy1624 moved this to Triage in SeaQL Dev Tracker May 18, 2022
@billy1624 billy1624 moved this from Triage to Next Up in SeaQL Dev Tracker May 23, 2022
@billy1624 billy1624 moved this from Next Up to In Progress in SeaQL Dev Tracker Jun 16, 2022
@billy1624
Copy link
Member

Hey @tyt2y3, do you mean removing one from SelectTwoMany?

From my understanding:

  • SelectTwo: is for selecting models in a one-to-one relationship
  • SelectTwoMany: is for selecting models in a one-to-many relationship

@billy1624 billy1624 self-assigned this Jun 22, 2022
@billy1624 billy1624 moved this from In Progress to Review in SeaQL Dev Tracker Jun 22, 2022
@billy1624 billy1624 moved this from Review to Done in SeaQL Dev Tracker Jul 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants