-
-
Notifications
You must be signed in to change notification settings - Fork 544
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
Support for alternative loading strategies #440
Comments
Currently not supported, as you said, you need to use QB if you do not want to load entities as the ORM does it by default (1 query per entity). The problem is not really in the query construction, but rather in the mapping. I am quite happy with how it works now as the mapping part is deadly simple, but I was planning to support mapping joined results too at some point of time. So not a priority for now I would say, having quite a lot of things I want to focus in following months. |
Thanks for the quick response. I would be happy to help implement this feature if it is only a matter of bandwidth. If you are willing, you can point me in the right direction with any designs you might already have in mind and I can take a stab at it. |
Great to hear that! I already started working on v4 and soon I want to split the ORM into several packages, so the time for a PR will come once that is done. Also I am not sure if we need all those options, the subquery one sounds a bit unnecessary (and also there is no support for subqueries in the QB currently, so that would be probably prerequisite). I would start with fetch joining as additional variant to the current way. I definitely want to have this option on the property level too. Not sure about the API you proposed, but that is not really important for now. We can always rename things later, and I would start with version where one can set this only at the property level. About the direction, I guess |
Great! I watch releases on this repo, but let me know once you feel you are ready to accept a PR. In the meantime, I'll poke around and get familiar with the codebase.
I definitely think we would wanna spec out what would be supported. My examples were mostly for demonstrative purposes using prior art from a great ORM 😄 Once we get to that point, we can discuss that here. |
Join with |
It's already supported (https://mikro-orm.io/docs/entity-manager/#searching-by-referenced-entity-fields), this issue is about being able to allow using single query and mapping the results to entities. Currently it will always fire 1 query per entity, with this change we could fire only 1 query for multiple entities. |
@willsoto So the split into packages is done (#475), feel free to PR this into As discussed, I would add the fetch joining as an alternative to current Not sure about the suggestion about collections, as Also I don't understand the |
@B4nan That is great! Thanks for following up with me. I'll spend some time hopefully tonight / this week and start browsing the |
Ok. So I've spent some time browsing the code and I think I have a good sense of where stuff needs to happen, but I wanna make sure I got it right. I will add a property named mikro-orm/packages/core/src/decorators/Property.ts Lines 58 to 62 in dfd731e
type Strategy = 'joined' | 'selectin'; It seems like I will have to make some changes to the QueryBuilder and the ObjectHydrator. You also mention the EntityLoader and the AbstractSqlDriver. I haven't gotten a sense of the order in which things should happen, so any guidance there would be good. If you have any additional thoughts or preferences, please let me know. Also let me know if I am missing anything. |
Not sure if you will need to change QB itself, this should be more about how Agreed with the rest, most of the work will be probably in the hydrator part. Also to be able to map multiple entities from one query, you will probably need to explicitly select all the fields aliased so you can be sure they won't collide (e.g. |
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
So I finally had some time to work on this. Although I was planing to do something else, until I realised that what we merged was really just a proof of concept and it was blocking me from implementing the lazy scalar props. So with my recent changes:
I also needed to redesign the await orm.em.findOneOrFail(Author2, { id: author2.id }, { populate: { books: LoadStrategy.JOINED } }); I also added few more My changes are not yet merged, but you can see it here: #585. Need to add more tests first to verify it actually works with all the use cases, also lazy props are not yet working in mongo, but should be merging this later today. |
I honestly can't commit since my schedule has become increasingly busy in the past couple of weeks. As much as I would like to see the feature through to completion, I don't want to be the reason you are holding up a release. If there are any smaller pieces of work (<5-6 hours) that can be done in isolation or with minimal interaction (thinking about rebases, merge conflicts, etc) feel free to point me to them. |
No worries, I should be able to finalize this myself.
Would be great if you could prepare some of the missing tests, and write a bit of docs, that should fit in few hours for sure :] |
You got it. I'll wait till #585 is merged for tests but I can start writing docs tomorrow most likely. |
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
This adds support for alternate load strategies. As of now, only one additional strategy is supported: `joined`. Currently, the only way to specify the strategy is on on the decorator for the relationship: ```ts @entity() export class Author2 { @onetomany({ entity: () => Book2, mappedBy: 'author', orderBy: { title: QueryOrder.ASC }, strategy: LoadStrategy.JOINED, // new property }) books!: Collection<Book2>; } ``` Related: #440
@B4nan It would be great to have some additional documentation on when you would want to use what strategy. I would expect it would have to do with the latency to the database, the complexity of the sql statement, etc. |
Apologies if this is documented somewhere, but I have not been able to find anything about it.
Is your feature request related to a problem? Please describe.
Not really a problem, but more of an inconvenience. It would be nice to be able to specify the Loading technique without having to drop to using the query builder.
Describe the solution you'd like
I would like to be able to specify the loading technique at the time I choose to load relationships.
Looking at the docs on Collections and seeing how relationships are currently loaded, one potential API for this could be something like:
Similar to SQLAlchemy, you could even specify the load type at the relationship level:
Describe alternatives you've considered
As mentioned above, the alternative right now seems to be to use the query builder.
Additional context
This feature seems fairly standard to ORMs. Some examples include SQLAlchemy and Objection.js
Thanks for the great project btw!
The text was updated successfully, but these errors were encountered: