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

[PIP] Simple data loader #1238

Merged
merged 16 commits into from
Dec 28, 2022
Merged

[PIP] Simple data loader #1238

merged 16 commits into from
Dec 28, 2022

Conversation

karatakis
Copy link
Contributor

@karatakis karatakis commented Nov 21, 2022

PR Info

Allows to query related entities from vector

Load one

[...]
    let bakers = baker::Entity::find()
        .all(&ctx.db)
        .await
        .expect("Should load bakers");

    let bakeries = bakers
        .load_one(bakery::Entity::find(), &ctx.db)
        .await
        .expect("Should load bakeries");
[...]

Load many

[...]
    let bakeries = bakery::Entity::find()
        .all(&ctx.db)
        .await
        .expect("Should load bakeries");

    let bakers = bakeries
        .load_many(baker::Entity::find().filter(baker::Column::Name.like("Baker%")), &ctx.db)
        .await
        .expect("Should load bakers");
[...]

New Features

  • Add simple Dataloader trait

* modify signature to accept statement outside
* add simple test
@karatakis karatakis marked this pull request as ready for review November 21, 2022 12:23
@karatakis
Copy link
Contributor Author

Its not ready yet. I need to do some testing

@karatakis karatakis marked this pull request as draft November 21, 2022 13:02
@karatakis karatakis marked this pull request as ready for review November 22, 2022 11:46
@tyt2y3
Copy link
Member

tyt2y3 commented Nov 23, 2022

The implementation looks great!

Made a few improvements:

  1. Use ValueTuple to replace Vec<Value> (less allocation)
  2. Remove Debug trait bounds (the panics should not happen anyway)
  3. Replace BTreeMap with HashMap (I don't see it being iterated)
  4. Slightly improve the test case

May be we still want more test cases?

I am tempted to change HashMap<String, _> to HashMap<ValueTuple, _>, but of course, Value is not hashable because of f32/f64. And I imagine the attempt to make a hashable version of Value to be quite difficult.

src/query/loader.rs Outdated Show resolved Hide resolved
src/query/loader.rs Outdated Show resolved Hide resolved
@karatakis
Copy link
Contributor Author

@tyt2y3 thanks for the feedback and the extra work.

@tyt2y3 do you want me to work on making Value Hash 'able?
If you do assign an issue and assign it to me to work on it 😄.
This is also needed in some cases for Seaography.

Is anything else needed for this issue ?

@tyt2y3
Copy link
Member

tyt2y3 commented Nov 24, 2022

Yes we can come back to this after we got a HashableValue .

Also may be awaiting @billy1624 's review

@tyt2y3 tyt2y3 mentioned this pull request Nov 25, 2022
@tyt2y3
Copy link
Member

tyt2y3 commented Nov 24, 2022

2.1. we should assume that the related entity might be shared; i.e. A1 & A2 both relates to B1, we will only get one B1, so we have to clone it

Can we also test this behaviour? I might be wrong but I suspect the current implementation would panic

@tyt2y3
Copy link
Member

tyt2y3 commented Nov 25, 2022

Created issue for HashableValue
#1254

@karatakis
Copy link
Contributor Author

karatakis commented Nov 25, 2022

Regarding #1238 (comment)

It didn't panic, but it was returning None. I fixed it by copying the values before returning.

Copy link
Member

@billy1624 billy1624 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @karatakis, sorry for coming in late. nice stuffs!! Thanks for the hard work!!

I think we should also implement the loader for M: ModelTrait. Providing a "complete" API, Vec<M> implemented LoaderTrait, M itself should also implement it.

Load one

let bakers = baker::Entity::find()
    .one(&ctx.db) // `one` here, instead of all
    .await?;

let bakeries: Option<_> = bakers // `Option<_>` here, instead of `Vec<Option<_>>`
    .load_one(bakery::Entity::find(), &ctx.db)
    .await?;

Load many

let bakeries = bakery::Entity::find()
    .one(&ctx.db) // `one` here, instead of all
    .await?;

let bakers: Vec<_> = bakeries // `Vec<_>` here, instead of `Vec<Vec<_>>`
    .load_many(baker::Entity::find().filter(baker::Column::Name.like("Baker%")), &ctx.db)
    .await?;

That means we need two extra associate types to type def the return type of both methods.

pub trait LoaderTrait {
    // Existing associated type
    type Model: ModelTrait;

    // New associated type to type def the return types
    type LoadOneResult;
    type LoadManyResult;

@tyt2y3
Copy link
Member

tyt2y3 commented Dec 28, 2022

I think we should also implement the loader for M: ModelTrait. Providing a "complete" API, Vec implemented LoaderTrait, M itself should also implement it.

Good point, although I think we don't have to mess the implementation, I suppose we can simply provide an implementation that just wraps a Vec of 1 item.

I want to merge this for now for 0.11

src/query/loader.rs Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[PIP] Simple data loader
3 participants