Fix #944 - allows to filter by relation by keeping EagerLoading enabled#950
Conversation
65686a3 to
f220063
Compare
|
Query is now better: This will work with the PaginationExtension as it doesn't alter the results, and it is optimized. |
f220063 to
105b6b2
Compare
|
WDYT? I'll add unit tests but I want to know first if this solution is fine to you or if you want to try another approach :). @api-platform/core-team |
|
Looks better, indeed. @ymarillet can you try if this patch fix the problem? |
| $container->setParameter('api_platform.eager_loading.enabled', $config['eager_loading']['enabled']); | ||
| $container->setParameter('api_platform.eager_loading.max_joins', $config['eager_loading']['max_joins']); | ||
| $container->setParameter('api_platform.eager_loading.force_eager', $config['eager_loading']['force_eager']); | ||
| $container->setParameter('api_platform.eager_loading.filter_relations', $config['eager_loading']['filter_relations']); |
There was a problem hiding this comment.
@teohhanhui suggestions about that parameter name ? \o/
There was a problem hiding this comment.
fetch_partial to true would mean we want to fetch a partial relation?
There was a problem hiding this comment.
Yes. So the default should be false.
Or perhaps partial_relations, partial_collections, partial_collection_fetch?
| ->booleanNode('enabled')->defaultTrue()->info('To enable or disable eager loading')->end() | ||
| ->integerNode('max_joins')->defaultValue(30)->info('Max number of joined relations before EagerLoading throws a RuntimeException')->end() | ||
| ->booleanNode('force_eager')->defaultTrue()->info('Force join on every relation. If disabled, it will only join relations having the EAGER fetch mode.')->end() | ||
| ->booleanNode('filter_relations')->defaultFalse()->info('Allow to filter the relation collection when the filter is on a nested property. By default, it will retrieve the full relation of the filtered resource. If enabled, only relations matching the filter will be returned.')->end() |
There was a problem hiding this comment.
Remind me to rewrite this for you. 😄
There was a problem hiding this comment.
When filtering on a nested property through a to-many relation, do not fetch the other items in the collection. Warning: this breaks round trip, as you cannot PUT the returned collection back to the parent property.
p/s: @soyuka Does this only happen when filtering on a nested property? Or whenever the other side of the relation is fetch-joined?
There was a problem hiding this comment.
Also, we need to warn that this would apply to every level in a multi-level nested property.
There was a problem hiding this comment.
Only when filtering on a nested property because it only joins the result matching that filter.
There was a problem hiding this comment.
When filtering by e.g. products?brands=/brands/1, doesn't it result in SQL something like:
SELECT ...
FROM products
INNER JOIN products_brands
ON products.id = products_brands.product_id
INNER JOIN brands
ON products_brands.brand_id = brands.id
WHERE brands.id = 1and thus:
{
"@id": "/products/1",
"brands": [
"/brands/1"
]
}even if product 1 has other brands?
This is not a nested property. So I think the problem manifests itself when filtering on any to-many relation.
There was a problem hiding this comment.
I really think we should not have this option, because it results in returning invalid data. ("Product 1 has 1 brand which is Brand 1.")
There was a problem hiding this comment.
Not sure I understood, what is the relation type on products_brands and brands?
There was a problem hiding this comment.
Many-to-many. products_brands is the join table.
There was a problem hiding this comment.
Yeah your right I think that this option is too much confusing, ManyToMany relations are working fine, I've added a test case anyway.
I'm removing the availability to filter on the relation. I think that the best to filter a relation would be to use subresource + filter.
|
Haha I will <3
…On Fri, 24 Feb 2017 at 18:08, Teoh Han Hui ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/Bridge/Symfony/Bundle/DependencyInjection/Configuration.php
<#950 (comment)>:
> @@ -49,6 +49,7 @@ public function getConfigTreeBuilder()
->booleanNode('enabled')->defaultTrue()->info('To enable or disable eager loading')->end()
->integerNode('max_joins')->defaultValue(30)->info('Max number of joined relations before EagerLoading throws a RuntimeException')->end()
->booleanNode('force_eager')->defaultTrue()->info('Force join on every relation. If disabled, it will only join relations having the EAGER fetch mode.')->end()
+ ->booleanNode('filter_relations')->defaultFalse()->info('Allow to filter the relation collection when the filter is on a nested property. By default, it will retrieve the full relation of the filtered resource. If enabled, only relations matching the filter will be returned.')->end()
Remind me to rewrite this for you. 😄
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#950 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABQr82anStSF9DznfHu8OFAzADViAO3cks5rfw6mgaJpZM4MDT7B>
.
|
105b6b2 to
f06a3a7
Compare
|
@teohhanhui I refactored the fix, it's much cleaner and simple now. It clones the query and uses a subquery with the where clause to find the root entity identifiers. Origin query: Fixed query: This will work with any relation (manytomany, manytoone etc.). I've removed the parameter to skip this extension. |
8cdbec9 to
36c1ad5
Compare
fb1d84d to
d03d4fe
Compare
|
ping @api-platform/core-team I think that this (as it's a bug fix) should target 2.0. Lmk. |
|
Yes, this is a bug fix. |
d03d4fe to
167e3be
Compare
167e3be to
495ea9e
Compare
|
Thank you very much @soyuka |
Fix api-platform#944 - allows to filter by relation by keeping EagerLoading enabled
|
filter_relations parameter seem not documented, it's still exist ? |
Nope. |
|
is it possible then to filter relations without a custom filters? @soyuka |
/!\ This is probably the worse code I've ever produced here and I hope we can find how to improve it together.
To fix #944 I needed to alter the query generated by the filters and the eager loading extension. To do so, I've added a
FilterEagerLoadingExtensionthat patches the Query generated by theFilterExtension.It runs directly after the
FilterExtensionand transforms the query so that it ends up doing something like:TODO:
forceEageris not setApologizes to Scrutinizer, that complexity index will be very high -_-.